面试题答案
一键面试寄生组合式继承的实现方式
- 创建一个临时构造函数:
function inheritPrototype(subType, superType) { let prototype = Object.create(superType.prototype); // 创建一个以superType.prototype为原型的新对象 prototype.constructor = subType; // 修正新对象的constructor属性指向子类型 subType.prototype = prototype; // 将子类型的原型设置为新创建的对象 }
- 定义超类型构造函数:
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; }
- 实现继承:
inheritPrototype(SubType, SuperType); SubType.prototype.sayAge = function() { console.log(this.age); };
相比其他继承方式的优势
- 相比原型链继承:
- 避免引用类型属性共享问题:原型链继承会导致所有实例共享超类型原型上的引用类型属性。例如在原型链继承中,如果超类型原型上有一个数组属性,所有子类型实例对该数组的修改都会相互影响。而寄生组合式继承通过借用构造函数的方式,在子类型实例中创建自己的实例属性,避免了这种问题。
- 可以向超类型传递参数:原型链继承无法在创建子类型实例时向超类型构造函数传递参数,而寄生组合式继承通过
SuperType.call(this, name)
这种方式可以轻松实现向超类型传递参数。
- 相比借用构造函数继承:
- 避免方法重复问题:借用构造函数继承虽然解决了实例属性的独立问题,但每个子类型实例都有一套自己的方法,造成了内存浪费。而寄生组合式继承通过将方法定义在共享的原型上,避免了方法的重复创建,提高了内存利用率。
- 原型链关系正常:借用构造函数继承没有建立完整的原型链关系,子类型实例无法访问超类型原型上的方法。寄生组合式继承通过
Object.create(superType.prototype)
正确地建立了原型链关系,使得子类型实例可以访问超类型原型上的方法。