繼承是面向?qū)ο缶幊讨杏忠环浅V匾母拍睿琂avaScript支持實現(xiàn)繼承,不支持接口繼承,實現(xiàn)繼承主要依靠原型鏈來實現(xiàn)的。
成都創(chuàng)新互聯(lián)不只是一家網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司;我們對營銷、技術(shù)、服務(wù)都有自己獨特見解,公司采取“創(chuàng)意+綜合+營銷”一體化的方式為您提供更專業(yè)的服務(wù)!我們經(jīng)歷的每一步也許不一定是最完美的,但每一步都有值得深思的意義。我們珍視每一份信任,關(guān)注我們的成都網(wǎng)站制作、做網(wǎng)站質(zhì)量和服務(wù)品質(zhì),在得到用戶滿意的同時,也能得到同行業(yè)的專業(yè)認(rèn)可,能夠為行業(yè)創(chuàng)新發(fā)展助力。未來將繼續(xù)專注于技術(shù)創(chuàng)新,服務(wù)升級,滿足企業(yè)一站式營銷型網(wǎng)站建設(shè)需求,讓再小的品牌網(wǎng)站制作也能產(chǎn)生價值!
原型鏈
首先得要明白什么是原型鏈,昆明北大青鳥建議可以在一篇文章看懂proto和prototype的關(guān)系及區(qū)別中講得非常詳細(xì)
原型鏈繼承基本思想就是讓一個原型對象指向另一個類型的實例
添加方法
在給SubType原型添加方法的時候,如果,父類上也有同樣的名字,SubType將會覆蓋這個方法,達到重新的目的。但是這個方法依然存在于父類中。
記住不能以字面量的形式添加,因為,上面說過通過實例繼承本質(zhì)上就是重寫,再使用字面量形式,又是一次重寫了,但這次重寫沒有跟父類有任何關(guān)聯(lián),所以就會導(dǎo)致原型鏈截斷。
問題
單純的使用原型鏈繼承,主要問題來自包含引用類型值的原型。
借用構(gòu)造函數(shù)
此方法為了解決原型中包含引用類型值所帶來的問題。
這種方法的思想就是在子類構(gòu)造函數(shù)的內(nèi)部調(diào)用父類構(gòu)造函數(shù),可以借助apply()和call()方法來改變對象的執(zhí)行上下文
傳遞參數(shù)
借助構(gòu)造函數(shù)還有一個優(yōu)勢就是可以傳遞參數(shù)
JavaScript中的function是萬能的,除了用于的函數(shù)定義,也可以用于類的定義。
JavaScript的繼承,說起來也是有點怪,不像C++和一些面向?qū)ο蟮恼Z言,他沒有public,private等訪問控制修飾,也沒有implement或其他特定的符號來說明是實現(xiàn)繼承。
關(guān)于javascript類的繼承可以參考一下下面的這個例子。
script?type="text/javascript"?
function?Person()?{
//?屬性?
this.Gender?=?"female";
this.Age?=?18;
this.Words?=?"Silence";
//?方法
this.shouting?=?function()?{
alert("開心哦!父類的方法");
}
}
//?繼承
function?Programmer()?{
this.base?=?Person;
}
Programmer.prototype?=?new?Person;
//?為子類添加新的方法
Programmer.prototype.typeCode?=?function()?{
alert("俺是敲代碼的!IT民工,很不開心。子類的方法");
}
//?調(diào)用示例
function?sayHello()?{
var?a?=?new?Programmer();
alert(a.Gender);?//?調(diào)用父類的屬性
a.shouting();?//?調(diào)用父類的方法
a.typeCode();?//?調(diào)用子類的方法
}????????
sayHello();
/script
上例中,首先是聲明一個person類,里面包含了一些屬性和方法,然后接著又聲明了一個programmer類,其中有個base屬性,這個屬性并不是
必需的,但是出于規(guī)范以及以后在查找對象所繼承的類時都需要寫上,然后是給programmer的原型對象(prototype)拷貝了person類;
于是便實現(xiàn)了類的繼承。
參考資料:
“繼承”是面向?qū)ο缶幊汤锩娼?jīng)常提及到的概念,它的目的是實現(xiàn)代碼復(fù)用。JavaScript并沒有“類”的概念,那么,它如何實現(xiàn)繼承呢?
(ES6有關(guān)鍵字class和extend,繼承的語法與Java等面向?qū)ο笳Z言類似,但是,ES6 class,只是JavaScript原型繼承的語法糖而已)
1. 類式繼承
關(guān)鍵點:通過構(gòu)造函數(shù)實現(xiàn)繼承。
父類:
function?Parent(name)?{
this.name?=?name?||?"parent";
}
Parent.prototype.say?=?function()?{
return?this.name;
}
子類:
function?Child()?{}
(1) 父類對象繼承
Child.prototype?=?new?Parent("child");
var?child?=?new?Child();
child.say();?//?"child"
特點:使用這種繼承模式,子類不僅僅會繼承父類原型上的方法/屬性,還會繼承父類自身的屬性。
這種模式的缺點是,在初始化父類對象指向給子類原型時,并不確定父類構(gòu)造函數(shù)的初始化參數(shù)(Child.prototype = new Parent("child");),而且,往往這些參數(shù)并不是子類需要的。
(2) 借用構(gòu)造函數(shù)
改造子類:
function?Child(){
Parent.apply(this,?arguments);
}
特點:使用這種繼承模式,子類只會繼承父類自身的屬性。
缺點很明顯,它無法從原型鏈中繼承任何方法/屬性。
(3) 共享原型
Child.prototype?=?Parent.prototype;
這種方式的缺點是,子類原型和父類原型共享一個對象,那么,子類如果修改原型,必然會影響父類。
(4) 臨時構(gòu)造函數(shù)
function?inherit(Child,?Parent)?{
var?F?=?function(){};?
F.prototype?=?Parent.prototype;?
Child.prototype?=?new?F();
}
特點:利用一個空函數(shù)F()充當(dāng)子類和父類之間的代理,既可以實現(xiàn)父類原型方法/屬性的繼承,又可以在子類原型上繼續(xù)擴展方法/屬性。
一般,我們可以利用ES5提供的新方法Object.create()來實現(xiàn)此類繼承。
Child.prototype?=?Object.create(Parent.prototype);
2. 通過復(fù)制屬性實現(xiàn)繼承
復(fù)制屬性分為淺拷貝和深拷貝。
淺拷貝不會復(fù)制對象類型,只會簡單的將對象引用指向子類,代碼如下:
function?extendDeep(parent,?child)?{?
var?key;?for(key?in?parent)?{??
if?(parent.hasOwnProperty(key)){???
if?(typeof?parent[key]?===?'object')?{????
child[key]?=?(parent[key].toString()?===?"[object?Array]")??[]:{};
extendDeep(parent[key],?child[key]);???
}?else?{
child[key]?=?parent[key];
}??
}?
}?
return?child;
}
3. "借用方法"模式復(fù)用父類函數(shù)
如果不想實現(xiàn)父子之間的完全繼承,僅僅期望子類實現(xiàn)父類中一個或多個方法,那么可以利用apply, call, bind來調(diào)用父類函數(shù),實現(xiàn)復(fù)用。
代碼如下:
parent.say.call(child,?"hello,?child!");
今天小編要跟大家分享的文章是關(guān)于Javascript繼承的常用4種方法。相信很多學(xué)習(xí)web前端開發(fā)技術(shù)的小伙伴在學(xué)習(xí)前端開發(fā)的javascript部分的時候,在面向?qū)ο蟮牟糠志秃茈y走下去了,主要的原因還是邏輯更加復(fù)雜了,需要理解的內(nèi)容比直觀的開發(fā)布局難一點。
在面向?qū)ο缶幊汤铮庋b和繼承是比較重要的,這中間,繼承是相對而言比較難理解的,因為javascript的繼承方式比較多,也有不同的優(yōu)缺點。今天小編為大家?guī)磉@篇文章就是來和大家一起說一說Javascript繼承的常用4種方法,希望能夠?qū)δ阌兴鶐椭?/p>
1、原型鏈繼承
核心:將父類的實例作為子類的原型
缺點:父類新增原型方法/原型屬性,子類都能訪問到,父類一變其它的都變了
2、構(gòu)造繼承
基本思想
借用構(gòu)造函數(shù)的基本思想就是利用call或者apply把父類中通過this指定的屬性和方法復(fù)制(借用)到子類創(chuàng)建的實例中。
因為this對象是在運行時基于函數(shù)的執(zhí)行環(huán)境綁定的。也就是說,在全局中,this等于window,而當(dāng)函數(shù)被作為某個對象的方法調(diào)用時,this等于那個對象。
call、apply方法可將一個函數(shù)的對象上下文從初始的上下文改變?yōu)橛蓆hisObj指定的新對象。
所以,這個借用構(gòu)造函數(shù)就是,new對象的時候(new創(chuàng)建的時候,this指向創(chuàng)建的這個實例),創(chuàng)建了一個新的實例對象,并且執(zhí)行Parent里面的代碼,而Parent里面用call調(diào)用了Person,也就是說把this指向改成了指向新的實例,所以就會把Person里面的this相關(guān)屬性和方法賦值到新的實例上,而不是賦值到Person上面,所以所有實例中就擁有了父類定義的這些this的屬性和方法。
因為屬性是綁定到this上面的,所以調(diào)用的時候才賦到相應(yīng)的實例中,各個實例的值就不會互相影響了。
核心:使用父類的構(gòu)造函數(shù)來增強子類實例,等于是復(fù)制父類的實例屬性給子類(沒用到原型)
缺點:方法都在構(gòu)造函數(shù)中定義,
只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法,無法實現(xiàn)函數(shù)復(fù)用,每個子類都有父類實例函數(shù)的副本,影響性能
3、組合繼承
組合繼承(所有的實例都能擁有自己的屬性,并且可以使用相同的方法,組合繼承避免了原型鏈和借用構(gòu)造函數(shù)的缺陷,結(jié)合了兩個的優(yōu)點,是最常用的繼承方式)
核心:通過調(diào)用父類構(gòu)造,繼承父類的屬性并保留傳參的優(yōu)點,然后再通過將父類實例作為子類原型,實現(xiàn)函數(shù)復(fù)用
缺點:調(diào)用了兩次父類構(gòu)造函數(shù),生成了兩份實例(子類實例將子類原型上的那份屏蔽了)
4、寄生組合繼承
核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調(diào)用兩次父類的構(gòu)造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點
缺點:堪稱完美,但實現(xiàn)較為復(fù)雜
以上就是小編今天為大家分享的關(guān)于web前端學(xué)習(xí)之Javascript繼承的常用4種方法的文章,希望本篇文章能夠?qū)φ趯W(xué)習(xí)web前端技術(shù)的小伙伴們有所幫助。想要了解更多web前端知識記得關(guān)注北大青鳥web培訓(xùn)官網(wǎng)。
文章轉(zhuǎn)載自公眾號:前端研究所
網(wǎng)頁名稱:繼承javascript,繼承上億遺產(chǎn)后豪門老公回來了
文章鏈接:http://chinadenli.net/article14/dsdsjde.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、網(wǎng)站營銷、網(wǎng)站導(dǎo)航、品牌網(wǎng)站建設(shè)、移動網(wǎng)站建設(shè)、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)