MST
星途 面试题库

面试题:JavaScript 原型链在继承中的应用及优化策略

阐述 JavaScript 如何利用原型链实现继承,并说明在实现继承过程中可能出现的性能问题以及相应的优化策略,给出优化前后的代码示例。
35.9万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

利用原型链实现继承的原理

在 JavaScript 中,每个对象都有一个 __proto__ 属性,指向它的原型对象。当访问一个对象的属性时,如果该对象本身没有这个属性,JavaScript 会沿着原型链向上查找,直到找到该属性或者到达原型链的顶端(null)。通过将一个构造函数的原型对象设置为另一个构造函数的实例,就可以实现继承。

代码示例(未优化)

// 父构造函数
function Animal(name) {
    this.name = name;
}

Animal.prototype.speak = function() {
    console.log(this.name +'makes a sound.');
};

// 子构造函数
function Dog(name, breed) {
    Animal.call(this, name);
    this.breed = breed;
}

// 使用原型链实现继承
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

// 创建实例
const myDog = new Dog('Buddy', 'Golden Retriever');
myDog.speak();

可能出现的性能问题

  1. 原型对象共享:所有实例共享原型对象上的属性和方法,如果在原型对象上定义了可变类型(如数组、对象),一个实例对该属性的修改会影响到其他实例。
  2. 不必要的属性查找:原型链过长会导致属性查找变慢,因为每次查找属性都需要沿着原型链向上遍历。

优化策略

  1. 使用 Object.create()Object.create() 方法创建一个新对象,使用现有的对象来提供新创建对象的 __proto__。这样可以避免不必要的实例化。
  2. 寄生组合式继承:结合 Object.create() 和借用构造函数,既避免了原型对象共享问题,又保持了原型链的优势。

优化后的代码示例(寄生组合式继承)

// 父构造函数
function Animal(name) {
    this.name = name;
}

Animal.prototype.speak = function() {
    console.log(this.name +'makes a sound.');
};

// 子构造函数
function Dog(name, breed) {
    Animal.call(this, name);
    this.breed = breed;
}

// 创建原型对象
function inheritPrototype(subType, superType) {
    const prototype = Object.create(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}

// 实现继承
inheritPrototype(Dog, Animal);

// 创建实例
const myDog = new Dog('Buddy', 'Golden Retriever');
myDog.speak();

通过这种方式,既利用了原型链实现继承,又避免了常见的性能问题。