Javascript繼承的6種模式總結
阿新 • • 發佈:2019-05-09
接收 基於 宋體 就是 調用 ava push property 構造函數
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 }
Javascript繼承的6種模式總結