Javascript继承的6种模式总结

1、原型链

 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())

原型链的问题:

  • 共享性
  • 在创建子类型的实例时,不能向超类型的构造函数中传递参数

2、借用构造函数

 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)

借用构造函数的问题:

  • 方法都在构造函数中定义
  • 无法继承超类型的原型

3、组合继承

组合继承是将原型链和借用构造函数的技术组合到一块,取其二者之长。

 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中最常用的继承模式。

4、原型式继承

道格拉斯·克罗克福德介绍了一种实现继承的方法,这种方法并没有使用严格意义上的构造函数。他的想法是借助原型可以基于已有的对象创建对象,同时还不必因为创建自定义类型。

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"

5、寄生式继承

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"

6、寄生组合式继承

前面说过,组合继承式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 }

猜你喜欢

转载自www.cnblogs.com/jim-blogs/p/10834532.html