繼承的實現方式之 組合繼承
阿新 • • 發佈:2020-07-15
基本形式
通過原型鏈繼承原型屬性及方法,通過假借建構函式繼承例項屬性及方法。
function SuperType(name){ this.name = name; this.colors = ["red", "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.prototype.sayAge = function(){ console.log(this.age); } let instance1 = new SubType("Jack", 19); instance1.colors.push("black"); console.log(instance1.colors);//["red", "blue", "black"] instance1.sayName();//Jack instance1.sayAge();//19 let instance2 = new SubType("Ann", 29); instance2.colors.push("pink"); console.log(instance2.colors);//["red", "blue", "pink"] instance2.sayName();//Ann instance2.sayAge();//29 delete instance1.colors; delete instance2.name; console.log(instance1.colors); //["red", "blue"] 是原型SuperType例項上的colors console.log(Object.getOwnPropertyNames(instance1));//["name", "age"]
優點:結合了原型鏈繼承和假借建構函式繼承的優點
- 可以繼承父類的原型屬性及方法
- 可以形成原型鏈,使得子類例項和父類原型間iinstanceof和isPropertyOf判斷為真
- 例項之間不用共享屬性
- 可以向父類建構函式傳參
缺點
SuperType建構函式被呼叫了兩次,第一次呼叫在改變子類原型時,把一個父類例項設為了子類原型;第二次呼叫在通過new呼叫子類建構函式時,假借了父類的建構函式繼承父類的例項屬性。
但在第一次呼叫以後,父類的例項屬性和方法實際成為了子類的原型屬性和方法,只是在建立物件假借建構函式時,這些原型方法被同名的例項方法隱藏了,實際訪問不到。因此,始終有一套訪問不到的屬性在子類的原型上,造成了空間的浪費。並且如果我們想刪除子類例項上的同名屬性,會發現刪除以後該屬性仍然能夠訪問到,因為原型上的屬性仍然存在。