淺析JavaScript的繼承和原型鏈_第1頁
淺析JavaScript的繼承和原型鏈_第2頁
淺析JavaScript的繼承和原型鏈_第3頁
淺析JavaScript的繼承和原型鏈_第4頁
淺析JavaScript的繼承和原型鏈_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第淺析JavaScript的繼承和原型鏈淺析JavaScript的繼承和原型鏈

JavaScript的繼承和原型鏈是我在學習前端過程中遇到的較為少有的難以理解的部分,這里便將我所有知道和了解到的東西記錄了下來,希望能夠給還在這里面苦苦掙扎的兄弟萌一點點小的幫助,也歡迎各位大佬批評指正。

二、構(gòu)造函數(shù)

2.1構(gòu)造函數(shù)的實例成員和靜態(tài)成員

構(gòu)造函數(shù)由實例成員和靜態(tài)成員二者組成,其中實例成員是在函數(shù)內(nèi)部通過this關(guān)鍵字添加的成員;只能通過實例化對象以后通過實例化對象進行訪問;而靜態(tài)成員是函數(shù)本身上添加的成員,只能通過構(gòu)造函數(shù)來訪問。

//創(chuàng)造一個構(gòu)造函數(shù)letFather=function(name,age){

//實例成員

=name;

this.age=age;

this.method=我是一個實例成員}

//靜態(tài)成員Father.like=mother

//檢驗實例對象是否能夠被構(gòu)造函數(shù)直接訪問console.log(Father.method);

//undefinedconsole.log(Father.like);

//mother

//實例化一個對象letfather=newFather(小王,27);

//檢驗靜態(tài)對象是否能夠被實例化對象訪問console.log();

//小王console.log(father.age);

//27console.log(father.like);

//undefined

2.2實例化對象的過程

通過new關(guān)鍵字可以通過構(gòu)造函數(shù)實現(xiàn)一個實例化對象,那么在具體實例化的過程中發(fā)生了什么呢?大致可以劃分為以下幾個步驟:

(1)創(chuàng)建一個空對象son{}

(2)為son準備原型鏈連接son.__proto__=Ftotype

(3)重新綁定this,使構(gòu)造函數(shù)的this指向新對象Father.call(this)

(4)為新對象屬性賦值

(5)返回thisreturnthis,此時的新對象就擁有了構(gòu)造函數(shù)的方法和屬性了

一個小問題:所有實例化對象的方法都是共享的嗎?

構(gòu)造函數(shù)的方法分為兩種,第一種為在函數(shù)內(nèi)部直接定義的方法,第二種為通過原型添加的方法;

//函數(shù)內(nèi)部直接定義的方法letFather=function(){

this.read=function(){

console.log(我是內(nèi)部定義的read方法!

}}//通過原型鏈添加的方法Ftotype.look=function(){

console.log(我是通過原型鏈定義的look方法!}

//實例化對象進行檢驗letfather1=newFather();letfather2=newFather();

father1.read();

//我是內(nèi)部定義的read方法!father2.read();

//我是內(nèi)部定義的read方法!console.log(father1.read===father2.read);

//falsefather1.look();

//我是通過原型鏈定義的look方法!father2.look();

//我是通過原型鏈定義的look方法!console.log(father1.look===father2.look);

/true

可以發(fā)現(xiàn),函數(shù)內(nèi)部直接定義的方法在每實例化一個新的對象以后,都會給這個方法分配一個新的內(nèi)存空間,而通過原型添加的方法便會共享一個空間。

一個小問題:所有實例化對象的屬性都是共享的嗎?

不存在內(nèi)存空間的問題,判斷時看其值是否相同;

letFather=function(name){

=name;}letfather1=newFather(小王

letfather2=newFather(小紅

console.log(===);

//falseletfather1=newFather(小王

letfather2=newFather(小王

console.log(===);

//true

因此我們可以總結(jié)一下定義構(gòu)造函數(shù)的基本規(guī)則,即公共屬性定義到構(gòu)造函數(shù)里面,公共方法我們放到原型對象身上。

3.1什么是原型

Ftotype就是原型,它是一個對象,也可以稱為原型對象。

3.2原型的作用是什么

原型的作用,就是共享方法。

我們通過Ftotype.method可以共享方法,不會反應(yīng)開辟空間存儲方法。

3.3原型中的this指向哪兒

原型中this的指向是實例。

四、原型鏈

原型鏈本人感覺是一個對于初學者或者說是部分前端菜雞(例如本人)來說特別難以理解的東西,為了讓下面的部分更容易理解,這里強行先記住以下幾點:

__proto__是每個對象都有的屬性,prototype是每個函數(shù)特有的方法;

每個對象的__proto__屬性都會指向自身構(gòu)造函數(shù)的prototype;

constructor屬性始終指向創(chuàng)建當前對象的構(gòu)造函數(shù);

Function.__proto__===Ftotype;

Ototype.__proto__===null也就是原型鏈的終點;

4.1什么是原型鏈

原型與原型層層相鏈接的過程即為原型鏈。

4.2原型鏈的應(yīng)用

對象可以使用構(gòu)造函數(shù)prototype原型對象的屬性和方法,就是因為對象有__proto__原型的存在每個對象都有__proto__原型的存在

letFather=function(name){

=name;}letfather=newFather(老王console.log(father.__proto__===Ftotype);

//true

//驗證上述說法中的第二條

4.3原型鏈圖

結(jié)合寫在最前面的幾點,理解上圖應(yīng)該問題不大了,圖中圈起來的部分就是駭人聽聞的原型鏈。

4.4原型鏈的查找方式

functionStar(name){

=name;

//(1)首先看obj對象身上是否有dance方法,如果有,則執(zhí)行對象身上的方法

this.dance=function(){

console.log(+1

}}//(2)如果沒有dance方法,就去構(gòu)造函數(shù)原型對象prototype身上去查找dance這個方法。Stotype.dance=function(){

console.log(+2};

//(3)如果再沒有dance方法,就去Object原型對象prototype身上去查找dance這個方法。Ototype.dance=function(){

console.log(+3};

//(4)如果再沒有,則會報錯。letobj=newStar(小紅obj.dance();

(1)首先看obj對象身上是否有dance方法,如果有,則執(zhí)行對象身上的方法。

(2)如果沒有dance方法,就去構(gòu)造函數(shù)原型對象prototype身上去查找dance這個方法。

(3)如果再沒有dance方法,就去Object原型對象prototype身上去查找dance這個方法。

(4)如果再沒有,則會報錯。

一個小問題:在原型上添加方法需要注意的地方

有兩種添加方法,第一種為上面的寫法,直接通過構(gòu)造函數(shù).prototype.方法名進行添加;第二種為重定義構(gòu)造函數(shù)的prototype,但是此種情況會丟失掉原有的constructor構(gòu)造器,所以一定要再連接回去,例子如下:

functionStar(name){

=name;}Stotype={

dance:function(){

console.log(重定義prototype

}}Stotype.constructor=Star;

另外,類似于Array、String這些內(nèi)置的類是不能這么處理的。

這里就長話短說,首先我們要明確繼承需要繼承哪些東西,在前文中我們提到了定義構(gòu)造函數(shù)的基本規(guī)則,即**公共屬性定義到構(gòu)造函數(shù)里面,公共方法我們放到原型對象身上。**我們所需要繼承的東西也不外乎就這二者,公共屬性的繼承可以通過call()或者apply()進行this的指向定義,而公共方法可以通過原型對象的賦值進行處理,因此我們很容易想到如下的方法:

//定義一個父類functionFather(name){

=name;}Ftotype.dance=function(){

console.log(Iamdancing};//定義一個子類functionSon(name,age){

Father.call(this,name);

this.age=age;}//通過賦值的方法連接Stotype=Ftotype;//為子類添加方法Stotype.sing=function(){

console.log(Iamsinging};

letson=newSon(小紅,100);

//此時父類也被影響了console.log(Ftotype)

//{dance:,sing:,constructor:}

很顯然,當我們只想修改子類里面的方法時,顯然上述方法不太合適;因此我們可以嘗試new一個新的父類出來,代碼如下:

functionFather(name){

=name;}Ftotype.dance=function(){

console.log(Iamdancing};functionSon(name,age){

Father.call(this,name);

this.age=age;}Stotype=newFather();Stotype.sing=function(){

console.log(Iamsinging};letson=newSon(小紅,100);console.log(Ftotype)

//{dance:,constructor:}

六、class語法糖

對于以前了解過面向?qū)ο缶幊痰某绦騿T來講,上述關(guān)于繼承的寫法屬實讓人有些難以接受,因此在es6里面新增了一個語法糖來更方便更便捷地書寫繼承,這里就直接上代碼了;

classFather{

constructor(name){

=name;

dance(){

console.log(我是++,我今年+this.age+歲,+我在跳舞

}}classSonextendsFather{

constructor(name,age){

super(name);

this.age=age;

sing(){

con

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論