最近一直在回顧js繼承方式,在閱讀《高級程序設計》第3版 的時候遇到一個問題,下面僅我的見解,若是有理解錯誤或者不一樣見解,歡迎一塊兒探討:函數
何謂寄生組合繼承,實質上分爲兩步:this
這樣就實現了繼承,具體代碼以下所示(書中原代碼):spa
function SuperType(name){ this.name = name; } SuperType.prototype.sayName = function(){ console.log(this.name); } function SubType(name, age){ SuperType.call(this, name); this.age = age; } function inheritPrototype(subType, superType){ const subPrototype = Object(superType.prototype); subPrototype.constructor = SubType; subType.prototype = subPrototype; } inheritPrototype(SubType, SuperType); SubType.prototype.sayAge = function(){ console.log(this.age); } const sub_1 = new SubType('liumin', '23'); sub_1.sayName(); sub_1.sayAge();
在inheritPrototype函數當中正是完成了上面的兩個步驟,可是注意這裏是經過Object函數建立一個對象賦值給subPrototype的,接下來咱們瞭解一下Object函數prototype
爲給定值建立一個對象包裝器,若是傳入的是undefined 或者 null,則返回一個空對象;不然返回一個給定值對應類型的對象;設計
console.log(Object(undefined)); console.log(Object(null)); console.log(Object('123')); console.log(Object(123));
輸出結果是:
指針
若是傳入的參數是一個對象,那麼經過Object返回的則是對這個對象的引用,以下所示:code
const person = { name:'xiaohong', age:'23', grade:'12', } const anotherPerson = Object(person); console.log(anotherPerson === person);
輸出結果:
person和anotherPerson引用的是同一塊內存地址,這與Object.create(obj)是有差異的,Object.create(obj)是在內存中新開闢一個空間對象
若是在上述的繼承方式中存在一個問題,若是以後經過子類的原型對象對父類中的sayName方法進行從新定義,這時候就會修改父類中的sayName方法,從而繼承父類的其餘子類中的sayName方法也就會被篡改掉,形成混亂。
例如:
假如定義第二個子類——SubTypeCopy:繼承
function SubTypeCopy(name, height){ SuperType.call(this, name); this.height = height; } inheritPrototype(SubTypeCopy, SuperType);
而後在第一個子類中從新定義sayName方法:圖片
SubType.prototype.sayName = function(){ console.log(`my name is:${this.name}`); } const sub_1 = new SubType('liumin', '23'); const sub_2 = new SubTypeCopy('liujie','180'); sub_1.sayName(); sub_2.sayName();
最後的輸出結果是:
由此能夠看出,SubTypeCopy中的sayName方法也發生了改變,若是將Object替換成Object.create(obj)方法,就不會存在這樣的問題。