原型链
思想
利用原型让一个引用类型继承另一个引用类型的属性和方法。
方式
将子类的原型设置为父类的实例。
实现
function SuperType() {}function SubType() {}SubType.prototype = new SuperType();SubType.prototype.constructor = SubType;复制代码
问题
- 问题1。最主要的问题来自包含引用类型值的原型。包含引用类型值的原型属性会被所有实例共享。
function SuperType() { this.number = [1, 2, 3];}function SubType() {}SubType.prototype = new SuperType();SubType.prototype.constructor = SubType;let ins1 = new SubType();let ins2 = new SubType();ins1.number[0] = 11;console.log(ins2.number); // [11, 2, 3] 复制代码
- 问题2。在创建子类型的实例时,不能向超类型的构造函数传递参数。实际上,应该说时没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。
借用构造函数
思想
在子类型的构造函数内部调用超类型的构造函数。
实际上就是将超类型的代码在子类中执行一遍,使子类型拥有超类型的属性的副本。
实现
function SuperType() { this.num = [1, 2, 3];}function SubType() { // 继承 SuperType // 注意需要用 call 或 apply SuperType.call(this);}复制代码
比较
-
相对于原型链继承,借用构造函数不存在引用类型的原型属性被所有实例共享的问题,因为每个实例都有超类中属性的副本。
-
可以向超类型构造函数传递参数
问题
- 在超类型的原型中定义的方法,对子类型是不可见的。
组合继承
思想
结合原型链和借用构造函数两种方式。
使用原型链实现对原型属性和方法的继承,使用借用构造函数实现对实例属性的继承。
实现
function SuperType() {}function SubType() { // 借用构造函数继承 SuperType.call(this);}// 原型链继承SubType.prototype = SuperType;SubType.prototype.constructor = SubType;复制代码
参考
- 《JavaScript 高级程序设计》(第3版)