Javascript繼承的6種模式總結

一、原型鏈

 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)

 

借用構造函數的問題:this

  • 方法都在構造函數中定義
  • 沒法繼承超類型的原型

三、組合繼承

組合繼承是將原型鏈和借用構造函數的技術組合到一塊,取其兩者之長。spa

 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中最經常使用的繼承模式。prototype

四、原型式繼承

道格拉斯·克羅克福德介紹了一種實現繼承的方法,這種方法並無使用嚴格意義上的構造函數。他的想法是藉助原型能夠基於已有的對象建立對象,同時還沒必要由於建立自定義類型。code

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最經常使用的繼承模式。但它也有本身的不足,組合繼承最大的問題就是不管什麼狀況下,都會調用兩次超類型構造函數:一次是在建立子類型原型的時候,另外一次是在子類型構造函數內部。blog

 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 }
相關文章
相關標籤/搜索