1 function Supertype () { 2 this.property = true 3 } 4 5 Supertype.prototype.getSuperValue = function () { 6 return this.property 7 } 8 9 function SubType () { 10 this.subproperty = false 11 } 12 13 // 继承了SuperType 14 SubType.prototype = new Supertype() 15 16 SubType.prototype.getSubValue = function () { 17 return this.subproperty 18 } 19 20 var instance = new SubType() 21 console.log(instance.getSuperValue())
原型链的问题:
1 function SuperType (name) { 2 this.name = name 3 } 4 5 function SubType () { 6 // 继承了SuperType,同时还传递了参数 7 SuperType.call(this, ‘Nicholas‘) 8 9 // 实例属性 10 this.age = 29 11 } 12 13 var instance = new SubType() 14 console.log(instance.name) 15 console.log(instance.age)
借用构造函数的问题:
组合继承是将原型链和借用构造函数的技术组合到一块,取其二者之长。
1 function SuperType (name) { 2 this.name = name 3 this.colors = [‘red‘, ‘blue‘, ‘green‘] 4 } 5 6 SuperType.prototype.sayName = function () { 7 console.log(this.name) 8 } 9 10 function SubType (name, age) { 11 // 继承属性 12 SuperType.call(this, name) 13 14 this.age = age 15 } 16 17 // 继承方法 18 SubType.prototype = new SuperType() 19 SubType.prototype.constructor = SubType 20 SubType.prototype.sayAge = function () { 21 console.log(this.age) 22 } 23 24 var instance1 = new SubType(‘Nicholas‘, 29) 25 instance1.colors.push(‘black‘) 26 console.log(instance1.colors) // "red,blue,green,black" 27 instance1.sayName() // "Nicholas" 28 instance1.sayAge() // 29 29 30 var instance2 = new SubType(‘Greg‘, 29) 31 console.log(instance2.colors) // "red,blue,green" 32 instance2.sayName() // "Greg" 33 instance2.sayAge() // 29
组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为Javascript中最常用的继承模式。
道格拉斯·克罗克福德介绍了一种实现继承的方法,这种方法并没有使用严格意义上的构造函数。他的想法是借助原型可以基于已有的对象创建对象,同时还不必因为创建自定义类型。
1 function object (o) { 2 function F() {} 3 F.prototype = o 4 return new F() 5 }
ECMAScript 5通过新增Object.create()方法规范了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。
1 var person = { 2 name: ‘Nicholas‘, 3 friends: [‘Shelby‘, ‘Court‘, ‘Van‘] 4 } 5 6 var anotherPerson = Object.create(person, { 7 name: { 8 value: ‘Greg‘ 9 } 10 }) 11 12 console.log(anotherPerson.name) // "Greg"
1 function createAnother (original) { 2 var clone = object(original) // 通过调用函数创建一个新对象 3 clone.sayHi = function () { // 以某种方式来增强这个对象 4 console.log(‘hi‘) 5 } 6 return clone // 返回这个对象 7 }
1 var person = { 2 name: ‘Nicholas‘, 3 friends: [‘Shelby‘, ‘Court‘, ‘Van‘] 4 } 5 6 var anotherPerson = createAnother(person) 7 anotherPerson.sayHi() // "Hi"
前面说过,组合继承式JavaScript最常用的继承模式。但它也有自己的不足,组合继承最大的问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。
1 function SuperType (name) { 2 this.name = name 3 this.colors = [‘red‘, ‘blue‘, ‘green‘] 4 } 5 6 SuperType.prototype.sayName = function () { 7 console.log(this.name) 8 } 9 10 function SubType (name, age) { 11 SuperType.call(this, name) // 第二次调用SuperType() 12 13 this.age = age 14 } 15 16 // 继承方法 17 SubType.prototype = new SuperType() // 第一次调用SuperType() 18 SubType.prototype.constructor = SubType 19 SubType.prototype.sayAge = function () { 20 console.log(this.age) 21 }
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承的基本模式如下所述。
1 function inheritPrototype(subType, superType) { 2 var prototype = object(superType.prototype) // 创建对象 3 prototype.constructor = subType // 增强对象 4 subType.prototype = prototype // 指定对象 5 }
1 function SuperType (name) { 2 this.name = name 3 this.colors = [‘red‘, ‘blue‘, ‘green‘] 4 } 5 6 SuperType.prototype.sayName = function () { 7 console.log(this.name) 8 } 9 10 function SubType (name, age) { 11 SuperType.call(this, name) 12 13 this.age = age 14 } 15 16 inheritPrototype(subType, superType) 17 18 SubType.prototype.sayAge = function () { 19 console.log(this.age) 20 }
原文:https://www.cnblogs.com/jim-blogs/p/10834532.html