1> 原型及原型鏈在繼承中起到了關鍵的做用。因此你必定要理解他們。
2> 不會JS中的OOP,你也太菜了吧!(第一篇)html
原型鏈繼承是經過建立Super的實例,並將該實例賦值給Sub.prototype來實現的。函數
實現的本質是:重寫子類型的原型對象,代之以超類型的實例。this
function Super(){ this.name = 'JChen___'; } Super.prototype.getSuperName = function(){ return this.name; } function Sub(){ this.subname = 'JChen___son'; } Sub.prototype = new Super(); //原型繼承體如今這裏 Sub.prototype.getSubName = function(){ return this.subname; } var instance = new Sub();
注意:此時instance.constructor如今指向的是Super的,這是由於Sub.prototype指向了Super.prototype,而Super.prototype.constructor = Super。spa
原型鏈的問題:相似於利用原型建立對象,原型共享的特性也是原型鏈繼承的最大問題。prototype
在解決原型中包含引用類型值所帶來的問題的過程當中,咱們開始使用一種叫作借用構造函數的技術。code
這種技術的基本思想至關簡單:在子類型構造函數的內部調用超類型構造函數。htm
這樣一來,就會在新子類對象上執行超類函數中定義的全部對象初始化代碼。結果,每一個子類的實力都會有本身的超類中屬性的副本了。對象
function Super2(name){ this.colors = ['red', 'blue']; this.name = name; } function Sub2(){ Super2.call(this, 'JChen___2'); //借用構造函數技術體如今這裏 this.age = 29; } var instance1 = new Sub2(); instance1.colors.push('black'); var instance2 = new Sub2(); instance2.colors.push('green');
藉助構造函數繼承的問題:blog
1): 方法都在構造函數中定義,沒法複用。繼承
2): 在超類型的原型中的方法對子類是不可見的。
組合繼承指的是將原型鏈和借用構造函數的技術組合到一塊,從而發揮兩者之長的一種繼承模式。
組合繼承的思路:使用原型鏈實現對方法和屬性的繼承,經過借用構造函數實現對實例屬性的繼承。
function Super3(name){ this.name = name; this.colors = ['red', 'blue']; } Super3.prototype.sayName = function(){ return this.name; } function Sub3(name, age) { Super3.call(this, name); this.age = age; } Sub3.prototype = new Super3(); //解決借用構造函數技術的缺點 Sub3.prototype.constructor = Sub3; //糾正原型繼承改變了的構造函數 Sub3.prototype.sayAge = function(){ return this.age; }
組合繼承避免了原型鏈和借用構造函數的缺陷,融合了他們的優勢,成爲JavaScript中最經常使用的繼承模式。
組合繼承的問題:兩次調用超類構造函數。
原型式繼承的思路:藉助原型能夠基於已有的對象建立新對象,同時還沒必要所以建立自定義類型。
function object(o){ //原型式繼承的關鍵 function F(){} F.prototype = o; return new F(); } var person = { name: 'JChen___4', colors: ['blue'] } var person1 = object(person); person1.name = 'JChen___4___2' person1.colors.push('red'); var person2 = object(person); person2.name = 'JChen___4___3'; person2.colors.push('green');
原型式繼承的問題:同原型鏈同樣,他也有共享的劣勢。
寄生式繼承的思路:建立一個僅用於封裝繼承過程的函數,該函數內部以某種方式來加強對象,最後再返回該對象
function createAnother(origin){ //寄生式繼承的關鍵 var clone = object(origin); clone.sayHi = function(){ return 'Hi'; }; return clone; } var person = { name: 'JChen___4', colors: ['blue'] } var person1 = createAnother(person);
寄生式繼承的問題:像構造函數同樣,因爲不能作到函數的複用而下降效率。
寄生組合式繼承:經過借用構造函數來借用屬性,經過原型鏈的混成形式來繼承方法。
其背後的思想是:沒必要爲了指定子類型的原型而調用超類型的構造函數,咱們須要的無非就是超類型的一個副本而已。
function object(o){ function F(){} F.prototype = o; return new F(); } function inheritProto(subType, superType){ //避免第一調用構造函數的關鍵 var proto = object(superType.prototype); proto.constructor = subType; subType.prototype = proto; } function Super6(name){ this.name = name; this.colors = ['red', 'blue']; } Super6.prototype.sayName = function(){ return this.name; } function Sub6(name, age){ Super6.call(this, name); this.age = age; } inheritProto(Sub6, Super6); Sub6.prototype.sayAge = function(){ return this.age; } var instance1 = new Sub6('JChen___6', '12'); instance1.colors.push('black');
開發人員廣泛認爲寄生組合式繼承是引用類型最理想的繼承範式。
這就是JavaScript中的6種繼承方式,若是你們可以畫出每一個繼承的原型鏈關係圖,那麼繼承就是小菜一碟了。