要搞懂JS繼承,咱們首先要理解原型鏈:每個實例對象都有一個__proto__屬性(隱式原型),在js內部用來查找原型鏈;每個構造函數都有prototype屬性(顯示原型),用來顯示修改對象的原型,實例.__proto__=構造函數.prototype=原型。原型鏈的特色就是:經過實例.__proto__查找原型上的屬性,從子類一直向上查找對象原型的屬性,繼而造成一個查找鏈即原型鏈。app
1.原型鏈繼承函數
咱們使用原型繼承時,主要利用sub.prototype=new super,這樣連通了子類-子類原型-父類。this
1 //父類,帶屬性 2 function Super(){ 3 this.flag = true; 4 } 5 //爲了提升複用性,方法綁定在父類原型屬性上 6 Super.prototype.getFlag = function(){ 7 return this.flag; 8 } 9 //來個子類 10 function Sub(){ 11 this.subFlag = false; 12 } 13 //實現繼承 14 Sub.prototype = new Super; 15 //給子類添加子類特有的方法,注意順序要在繼承以後 16 Sub.prototype.getSubFlag = function(){ 17 return this.subFlag; 18 } 19 //構造實例 20 var es5 = new Sub;
缺點:構造函數原型上的屬性在全部該構造函數構造的實例上是共享的,即屬性沒有私有化,原型上屬性的改變會做用到全部的實例上。es5
2.構造函數繼承spa
在構造子類構造函數時內部使用call或apply來調用父類的構造函數.net
function Super(){ this.flag = true; } function Sub(){ Super.call(this) //若是父類能夠須要接收參數,這裏也能夠直接傳遞 } var obj = new Sub(); obj.flag = flase; var obj_2 = new Sub(); console.log(obj.flag) //依然是true,不會相互影響
優缺點:實現了屬性的私有化,可是子類沒法訪問父類原型上的屬性。prototype
3.組合繼承code
利用構造函數和原型鏈的方法,能夠比較完美的實現繼承對象
function Super(){ this.flag = true; } Super.prototype.getFlag = function(){ return this.flag; //繼承方法 } function Sub(){ this.subFlag = flase Super.call(this) //繼承屬性 } Sub.prototype = new Super; var obj = new Sub(); Sub.prototype.constructor = Sub; Super.prototype.getSubFlag = function(){ return this.flag; }
注:blog
這裏還有個小問題,Sub.prototype = new Super; 會致使Sub.prototype的constructor指向Super;然而constructor的定義是要指向原型屬性對應的構造函數的,Sub.prototype是Sub構造函數的原型,因此應該添加一句糾正:Sub.prototype.constructor = Sub;
4.寄生繼承
即將sub.prototype=new super改成sub.prototype=Object.creat(supper.prototype),避免了組合繼承中構造函數調用了兩次的弊端。
轉:https://blog.csdn.net/qq_25461519/article/details/81060130