一. 原型鏈繼承
function Person() { //被繼承的函數(shù)叫做超類(lèi)型(父類(lèi),基類(lèi)) this.name='mumu'; this.age='18'; } Person.prototype.name='susu';//當(dāng)屬性名相同時(shí)需就近原則,先在實(shí)例里面查找,沒(méi)找到再到原型里找 function Worker(){ //繼承的函數(shù)叫做子類(lèi)型(子類(lèi),派生類(lèi)) this.job='student'; } Worker.prototype=new Person();//通過(guò)原型鏈繼承,超類(lèi)型實(shí)例化后的對(duì)象實(shí)例,賦值給子類(lèi)的原型屬性 var p2=new Worker(); console.log(p2.name); console.log(p2 instanceof Object);//ture 所有的構(gòu)造函數(shù)都繼承自O(shè)bject
以上實(shí)現(xiàn)繼承關(guān)鍵在于:Worker.prototype=new Person(); 將Worker的原型成為Person的一個(gè)實(shí)例,通過(guò)原型鏈繼承。
注意:在使用原型鏈實(shí)現(xiàn)繼承時(shí),不能使用對(duì)象字面量創(chuàng)建原型方法,因?yàn)檫@樣會(huì)中斷關(guān)系而重寫(xiě)原型鏈。
原型鏈繼承問(wèn)題:
1.出現(xiàn)引用共享問(wèn)題,他們還是共用一個(gè)空間,子類(lèi)會(huì)影響父類(lèi)
2.在創(chuàng)建子類(lèi)型的實(shí)例時(shí),不能像超類(lèi)型的構(gòu)造函數(shù)中傳遞參數(shù)。
那么如何解決原型鏈的兩個(gè)問(wèn)題呢?那就繼續(xù)看下面的繼承方式吧~
二. 借用構(gòu)造函數(shù)繼承(也叫對(duì)象冒充,偽造對(duì)象或經(jīng)典繼承)
簡(jiǎn)單分析下以上使用借用構(gòu)造函數(shù)的原理:Person.call(this,name,age);這句代碼調(diào)用父級(jí)構(gòu)造函數(shù),繼承父級(jí)屬性,使用call方法調(diào)用Person構(gòu)造函數(shù)改變函數(shù)執(zhí)行時(shí)候的this, 這里的this-> new出來(lái)的一個(gè)Worker對(duì)象 構(gòu)造函數(shù)偽裝方法:把Worker傳給上面的Person。
當(dāng)引用類(lèi)型放在構(gòu)造函數(shù)里面的時(shí)候就不會(huì)被共享,所以p2不受影響。
這里借用構(gòu)造函數(shù)繼承方式就解決了原型鏈不能傳遞參數(shù)以及引用類(lèi)型共享的問(wèn)題。
小知識(shí):call()和apply()方法可以改變函數(shù)執(zhí)行的作用域, 簡(jiǎn)言之就是改變函數(shù)中this指向的內(nèi)容。
call()和apply()都接受兩個(gè)參數(shù):第一個(gè)是在其中運(yùn)行函數(shù)的作用域,另一個(gè)是傳遞的參數(shù)。
call和apply的區(qū)別就是參數(shù)的不同.
call中的參數(shù)必須是一個(gè)個(gè)枚舉出來(lái)的.
apply中的參數(shù)必須是數(shù)組或者是arguments對(duì)象
那么問(wèn)題來(lái)了:為什么p1.showName()結(jié)果是錯(cuò)誤的呢?----因?yàn)榻栌脴?gòu)造函數(shù)繼承方式只能繼承構(gòu)造函數(shù)里的屬性和方法。這里也就發(fā)現(xiàn)了借用構(gòu)造函數(shù)的一個(gè)問(wèn)題。
注意:由于把方法都放在構(gòu)造函數(shù)里,每次我們實(shí)例化就會(huì)分配內(nèi)存空間給它造成資源的浪費(fèi),所以一般我們都是把方法放在原型里,屬性放在構(gòu)造函數(shù)里。
借用構(gòu)造函數(shù)繼承問(wèn)題:
因?yàn)榻栌脴?gòu)造函數(shù)只能繼承構(gòu)造函數(shù)里的屬性和方法,在超類(lèi)型的原型中定義的方法對(duì)子類(lèi)而言是不可見(jiàn)的,所以就相當(dāng)于沒(méi)有了原型。結(jié)果所有的方法都只能在構(gòu)造函數(shù)里定義,因此就沒(méi)有函數(shù)復(fù)用了。
那么如何解決借用構(gòu)造函數(shù)所產(chǎn)生的問(wèn)題呢?那就要看下面這種繼承方式了
三. 組合繼承(偽經(jīng)典繼承)
組合繼承:將原型鏈與借用構(gòu)造函數(shù)結(jié)合。
思路:通過(guò)使用原型鏈實(shí)現(xiàn)原型上的屬性和方法繼承,借用構(gòu)造函數(shù)實(shí)現(xiàn)實(shí)例屬性的繼承
以上的例子Person.call(this,name,age);借用構(gòu)造函數(shù)繼承了屬性
Worker.prototype=new Person();原型鏈繼承了方法 , 避免了兩者的缺點(diǎn),融合了它們的優(yōu)點(diǎn),成為最常用的繼承模式。
組合繼承的問(wèn)題:
調(diào)用兩次超類(lèi)型構(gòu)造函數(shù),一次是在創(chuàng)建子類(lèi)型原型時(shí),另一次是在子類(lèi)型的構(gòu)造函數(shù)內(nèi)部。
要解決這個(gè)問(wèn)題就要用到寄生組合式繼承方式了。
四. 原型式繼承
簡(jiǎn)單分析下:function object(proto)是一個(gè)臨時(shí)中轉(zhuǎn)函數(shù),里面的參數(shù)proto表示將要傳遞進(jìn)入的一個(gè)對(duì)象,F(xiàn)()構(gòu)造函數(shù)是臨時(shí)新建的對(duì)象,用來(lái)存儲(chǔ)傳遞過(guò)來(lái)的對(duì)象,F(xiàn).prototype = proto;將對(duì)象實(shí)例賦值給F構(gòu)造函數(shù)的原型對(duì)象,最后返回傳遞過(guò)來(lái)的對(duì)象的對(duì)象實(shí)例。原型式繼承還是會(huì)共享引用類(lèi)型的屬性。
五. 寄生式繼承
六. 寄生組合式繼承
這種方法也是現(xiàn)在實(shí)現(xiàn)繼承方法中最完美的,也是最理想的。
以上這篇JavaScript繼承學(xué)習(xí)筆記【新手必看】就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com