MST

星途 面试题库

面试题:JavaScript 中 prototype 链继承存在哪些缺陷?如何改进?

在深入了解 JavaScript 的 prototype 特性继承时,会发现 prototype 链继承存在一些问题。请分析至少两个 prototype 链继承的缺陷,并针对这些缺陷提出相应的改进方法,同时给出改进后的代码示例。
42.0万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

prototype链继承的缺陷

  1. 原型中属性共享问题:所有实例会共享原型对象上的属性,这意味着一个实例对引用类型属性的修改会影响其他实例。例如,若原型中有一个数组属性,一个实例向该数组添加元素,其他实例的该数组也会发生变化。
  2. 无法向超类型构造函数传参:在创建子类型实例时,无法直接向超类型构造函数传递参数,导致超类型的初始化受到限制。

改进方法及代码示例

  1. 借用构造函数解决属性共享问题:在子类型构造函数内部调用超类型构造函数,通过 callapply 方法,将超类型构造函数的作用域绑定到子类型实例上,这样每个实例都有自己独立的属性副本。
function SuperType(name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}

function SubType(name, age) {
    SuperType.call(this, name);
    this.age = age;
}
  1. 组合继承解决无法传参问题:将原型链继承和借用构造函数继承结合起来。先通过借用构造函数继承实例属性,保证每个实例有自己独立的属性,再通过原型链继承共享方法。
function SuperType(name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}

SuperType.prototype.sayName = function() {
    console.log(this.name);
};

function SubType(name, age) {
    SuperType.call(this, name);
    this.age = age;
}

SubType.prototype = Object.create(SuperType.prototype);
SubType.prototype.constructor = SubType;

SubType.prototype.sayAge = function() {
    console.log(this.age);
};

let instance1 = new SubType('Nicholas', 29);
let instance2 = new SubType('Greg', 27);

instance1.colors.push('black');
console.log(instance1.colors); // ["red", "blue", "green", "black"]
console.log(instance2.colors); // ["red", "blue", "green"]

instance1.sayName(); // Nicholas
instance1.sayAge(); // 29