摘要:組合繼承最大的問題就是無論在什么情況下,都會調用兩次超類型構造函數一次是在創建子類型原型的時候。好在,我們已經找到了解決這個問題方法寄生組合式繼承所謂寄生組合式繼承,即通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。
寄生組合式繼承
組合繼承是JavaScript最常用的繼承模式。
不過,它也有自己的不足。
組合繼承最大的問題就是無論在什么情況下,都會調用兩次超類型構造函數:
一次是在創建子類型原型的時候。
另外一次是在子類型構造函數內部。
子類型最終會包含超類型對象的全部實例屬性,但我們不得不在調用子類型構造函數時重寫這些屬性。
function SuperType(name) { this.name = name; this.colors = ["red", "green", "blue"]; } SuperType.prototype.sayName = function(){ console.log(this.name); } function SubType(name, age) { SuperType.call(this, name); //第二次調用父類型 this.age = age; } SubType.prototype = new SuperType(); // 第一次調用父類型 /* //到這里SubType的原型 SubType.prototye = { name: undefined, colors: ["red", "green", "blue"], __proto__: { constructor: SuperType, sayName: function(){ console.log(this.name); } } */ SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function() { console.log(this.age); } /* //到這里SubType的原型 SubType.prototye = { name: undefined, colors: ["red", "green", "blue"], constructor: SubType, sayAge: function() { console.log(this.age); }, __proto__: { constructor: SuperType, sayName: function(){ console.log(this.name); } } */ var sub = new SubType(); /* // SubType的實例對象sub,其實是這樣的 sub = { name: undefined, colors: ["red", "green", "blue"], age: undefined, __proto__: { name: undefined, colors: ["red", "green", "blue"], constructor: SubType, sayAge: function() { console.log(this.age); }, __proto__: { constructor: SuperType, sayName: function(){ console.log(this.name); } } } } */
在第一次調用SuperType構造函數時,SubType.prototype會得到兩個屬性:name和colors;它們都是SuperType的實例屬性, 只不過現在位于SubType的原型中。
如果我們調用SubType構造函數時,又會調用一次SuperType構造函數,這一次有在新對象上創建了實例屬性name和colors。于是,這兩個屬性就屏蔽了原型中的兩個同名屬性。
有兩組name和colors屬性: 一組在實例上,一組在SubType原型中。
這就是調用兩次SuperType函數的結果。
好在,我們已經找到了解決這個問題方法——寄生組合式繼承
所謂寄生組合式繼承,即通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。
其背后的基本思路:不必為了指定子類型的原型而調用超類型的構造函數,我們所需要的無非就是超類型原型的一個副本而已。本質上,就是使用寄生式繼承來繼承超類型的原型,然后再將結果指定給子類型的原型。
function object(o){ function F(){}; F.prototype = o; return new F(); } function SuperType(name) { this.name = name; this.colors = ["red", "green", "blue"]; } SuperType.prototype.sayName = function(){ console.log(this.name); } function SubType(name, age){ SuperType.call(this, name); this.age = age; } function inheritPrototype(SubType, SuperType){ var prototype = object(SuperType.prototype); prototype.constructor = SubType; SubType.prototype = prototype; } inheritPrototype(SubType, SuperType); var instance = new SubType("Shaw", 18); instance.sayName(); //"Shaw"
這個實例中的inheritPrototype()函數實現了寄生組合式繼承的最簡單形式。
這個函數接收兩個參數: 子類型構造函數和超類型構造函數。
在函數內部,第一步是創建超類型原型的一個副本。第二步是為創建的副本添加constructor屬性,從而彌補因為重寫原型而失去的默認的constructor屬性。 最后一步,將新創建的對象(副本)賦值給子類型的原型。
這樣,我們就可以調用inheritPrototype()函數的語句,去替換前面例子中為子類型原型賦值的語句了。
這個例子的高效率體現在它只調用了一次SuperType()構造函數,并且因此避免了在SubType.prototype上面創建不必要的、多余的屬性。與此同時,原型鏈還能保持不變。
因此,還能夠正常使用instanceof和isPrototypeOf()。
開發人員普遍認為寄生組合式繼承是引用類型最理想的繼承范式。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98652.html
摘要:以下是幾種中實現繼承的方式方法它們也是各自有各自的優缺點選擇哪一種根據自己的應用而定最適合自己的才是最好的通過原型鏈繼承通過原型對象繼承缺點引用類型的值在原型中會被所有實例共享不能向超類的構造函數中傳遞參數借用構造函數繼承借用構造函數繼承是 以下是幾種js中實現繼承的方式方法,它們也是各自有各自的優缺點,選擇哪一種根據自己的應用而定,最適合自己的才是最好的. 通過原型鏈繼承 funct...
摘要:寄生式繼承的思路與寄生構造函數和工廠模式類似,即創建一個僅用于封裝繼承過程的函數,該函數在內部已某種方式來增強對象,最后再像真的是它做了所有工作一樣返回對象。 這篇本來應該是作為寫JS 面向對象的前奏,只是作為《javascript高級程序設計》繼承一章的筆記 原型鏈 code 實現 function SuperType() { this.colors = [red,blu...
摘要:除此之外,在超類型的原型中定義的方法,對子類型而言也是不可兼得,結果所有類型都只能用構造函數模式。創建對象增強對象指定對象繼承屬性這個例子的高效率體現在它只調用了一次構造函數。 1、原型鏈 原型鏈的基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。構造函數、原型和實例的關系:每個構造函數都有一個原型對象;原型對象都包含著一個指向構造函數的指針;實例都包含一個指向原型對象的...
摘要:因為這造成了繼承鏈的紊亂,因為的實例是由構造函數創建的,現在其屬性卻指向了為了避免這一現象,就必須在替換對象之后,為新的對象加上屬性,使其指向原來的構造函數。這個函數接收兩個參數子類型構造函數和超類型構造函數。 最近一直在研究js面向對象,原型鏈繼承是一個難點,下面是我對繼承的理解以下文章借鑒自CSDN季詩筱的博客 原型鏈繼承的基本概念: ES中描述了原型鏈的概念,并將原型鏈作為實現...
摘要:通常有這兩種繼承方式接口繼承和實現繼承。理解繼承的工作是通過調用函數實現的,所以是寄生,將繼承工作寄托給別人做,自己只是做增強工作。適用基于某個對象或某些信息來創建對象,而不考慮自定義類型和構造函數。 一、繼承的概念 繼承,是面向對象語言的一個重要概念。通常有這兩種繼承方式:接口繼承和實現繼承。接口繼承只繼承方法簽名,而實現繼承則繼承實際的方法。 《JS高程》里提到:由于函數沒有簽名,...
閱讀 2218·2021-09-30 09:47
閱讀 975·2021-08-27 13:01
閱讀 2965·2019-08-30 15:54
閱讀 3690·2019-08-30 15:53
閱讀 831·2019-08-29 14:07
閱讀 718·2019-08-28 18:16
閱讀 802·2019-08-26 18:37
閱讀 1412·2019-08-26 13:27