您好,登錄后才能下訂單哦!
本文實例講述了JavaScript寄生組合式繼承。分享給大家供大家參考,具體如下:
其實《JavaScript高級程序設計》這本書中已經有完整代碼了,只要把代碼讀懂就知道這個繼承是怎么回事。
首先,在js中,給對象定義屬性有兩種方式:
//通過執行構造函數設置屬性 function A(){ this.a = 1; } //通過原型設置屬性 A.prototype.b = 1;
所以:
一個類Sub要繼承另一個類Super,需要繼承父類的prototype下的屬性,還要執行一下父類的構造函數。
即一個類Sub要繼承另一個類Super,既要通過原型鏈實現對原型屬性和方法的繼承,又要通過在子類構造函數內調用父類構造函數實現對實例屬性的繼承。
1. 繼承prototype下的屬性
上面可以看到,Super類的prototype下的屬性是沒有被繼承的,因此下面還需要繼承這一部分。
直接「=」肯定不行,因為Sub.prototype中修改屬性后,不能影響Super.prototype里面的對象,即不能Sub.prototype=Super.prototype
。
首先寫一個創建對象副本的方法
function object(o){ function A(){} A.prototype = o var ox = new A() return ox }
上面的函數得到的對象ox,擁有了對象o的全部屬性(在原型鏈上),而修改ox的屬性,不會影響到o,相當于把o復制了一份。
原型式繼承就是上面的“object”函數,在很多類庫源碼中都能發現它的身影
簡單而言,原型式繼承就是不用實例化父類了,直接實例化一個臨時副本實現了相同的原型鏈繼承。(即子類的原型指向父類副本的實例從而實現原型共享)
tips:總所周知,原型鏈繼承是子類的原型指向父類的實例從而實現原型共享,而原型式繼承是子類的原型指向父類副本的實例從而實現原型共享。
ECMAScirpt 5通過新增Object.create()
方法規范化了原型式繼承。
使用object方法,就可以將Super.prototype的屬性「復制」到Sub.prototype上了,當然這兒還需要修正一下constructor的指向。
function inherit(subType,superType){ var prototype=Object.create(superType.prototype); prototype.constructor=subType; subType.prototype=prototype; }
2. 分別執行父類和子類的構造函數,繼承這部分下的屬性:
//父類 function Super(){ this.sss=1 } //子類 function Sub(){ //arguments是Sub收到的參數,將這個參數傳給Super Super.apply(this, arguments) } //實例 sub = new Sub()
Super.apply(this, arguments)
這一句,將Super類作為一個普通函數來執行,但是Super類的this被換成了Sub類的this,Sub收到的參數也傳給了Super
最后執行結果相當于sub.sss=1
附上各種繼承方式的特點和優缺點
曾經一段時間因為javascript關于類實現繼承的不規范,導致各種各樣實現繼承的代碼;而實際上不管代碼怎么變,繼承都基于兩種方式:
1.通過原型鏈,即子類的原型指向父類的實例從而實現原型共享。
2.借用構造函數,即通過js的apply、call實現子類調用父類的屬性、方法;
原型鏈方式可以實現所有屬性方法共享,但無法做到屬性、方法獨享(例如Sub1修改了父類的函數,其他所有的子類Sub2、Sub3...想調用舊的函數就無法實現了);
而借用構造函數除了能獨享屬性、方法外還能在子類構造函數中傳遞參數,但代碼無法復用。總體而言就是可以實現所有屬性方法獨享,但無法做到屬性、方法共享(例如,Sub1新增了一個函數,然后想讓Sub2、Sub3...都可以用的話就無法實現了,只能Sub2、Sub3...各自在構造函數中新增)。
組合繼承就是把以上兩種繼承方式一起使用,把共享的屬性、方法用原型鏈繼承實現,獨享的屬性、方法用借用構造函數實現,所以組合繼承幾乎完美實現了js的繼承;為什么說是“幾乎”?因為認(dan)真(teng)的geek們發現組合繼承有一個小bug,實現的時候調用了兩次超類(父類),性能上不合格啊有木有!怎么解決呢?于是“寄生繼承”就出來了。
寄生繼承(原型式繼承)就是不用實例化父類了,直接實例化一個臨時副本實現了相同的原型鏈繼承。(即子類的原型指向父類副本的實例從而實現原型共享)
“寄生組合繼承”用了“寄生繼承”修復了“組合繼承”的小bug,從而讓js完美實現繼承了。
實例代碼:
function SuperType(name,colors){ this.name=name; this.colors=colors; } SuperType.prototype.getSuperProperty=function(){ return this.name; } function SubType(job,name,colors){ SuperType.call(this,name,colors); this.job=job; } SubType.prototype.getSubPrototype=function(){ return this.job; } function inherit(subType,superType){ var prototype=Object.create(superType.prototype); prototype.constructor=subType; subType.prototype=prototype; } inherit(SubType,SuperType); var instance=new SubType("doctor","John",["red","green"]); console.log(instance.getSubPrototype()); //輸出"doctor" console.log(instance.getSuperProperty()); //輸出"John",成功調用在父類原型定義的方法
屬性繼承代碼是SuperType.call(this,name,colors);
原型繼承代碼是inherit(SubType,SuperType);
更多關于JavaScript相關內容感興趣的讀者可查看本站專題:《javascript面向對象入門教程》、《JavaScript錯誤與調試技巧總結》、《JavaScript數據結構與算法技巧總結》、《JavaScript遍歷算法與技巧總結》及《JavaScript數學運算用法總結》
希望本文所述對大家JavaScript程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。