1. 程式人生 > >js之原型鏈與繼承

js之原型鏈與繼承

js中的原型鏈是比較難理解的一部分知識,而繼承又是依賴於原型鏈,所以原型鏈是我們必須去掌握的。在學習原型鏈之前,我們需要去介紹一下原型。建議這部分重在理解,不推薦死記硬背。


1、原型

js中只有函式物件才有原型,原型也是個物件。例如,我們建立一個save函式,通過typeof來檢視其型別,返回值是”object”,說明其實一個物件。

圖1 函式物件
那麼,函式的原型包含哪些內容呢?通過列印輸出,我們可以看到,其原型包含兩部分,一是constructor,二是proto。我們首先了解下constructor,後文會介紹proto
這裡寫圖片描述
圖2 函式物件的原型
學過java的都知道constructor是構造器的意思,其包含有關構造器的一些資訊,比如引數、呼叫者等。
前面說過只有函式物件才有原型,那麼普通物件有沒有呢?下面通過例項驗證,通過save構造出一個物件fileSave。
這裡寫圖片描述


圖3 普通物件
從上面的例子看出,普通物件是沒有原型的,但是其有proto屬性。
小結:從以上分析,我們學到函式物件有原型屬性,普通物件沒有原型屬性。

2、原型鏈

原型鏈的實現是依賴proto屬性的,其可以理解為C語言中的指標,java中的引用。在js中,proto指向的是什麼呢?還是丟擲例項,下面通過列印輸出fileSave的proto屬性:
這裡寫圖片描述
圖4 物件的proto
你是不是有所發現,fileSave的proto值和圖2中的save函式物件的prototype一樣,即proto指向save的原型。我們知道fileSave物件是通過new save();建立的,故我們得出結論fileSave的proto

指向其建構函式物件的原型。為了驗證結果,我們再次通過save建立一個物件imageSave,看一下它的proto屬性值。
這裡寫圖片描述
我們再次發現,imageSave的proto指向了save的原型。因此,我們可以知道物件的proto指向其建構函式的原型。那麼,save也是一個物件,它的prto應該指向它的建構函式的原型,即Function的原型。
這裡寫圖片描述
另外,我們從第一節知道原型也是物件,其proto屬性的指向又是如何呢?以例項說話,下面打印出save.prototype.proto值。
這裡寫圖片描述
圖5 save.prototype.proto
從圖5知,save.prototype.proto的值是Object的原型。我們很好奇,Obejct.prototype 的proto
的值,打印出來看看。
這裡寫圖片描述
是null,可以理解,畢竟其實最頂層的物件啦。
從上面的分析得出下面的鏈圖:
這裡寫圖片描述
圖6 原型鏈
小結:通過這一節的分析,我們學到原型鏈的實現是依靠物件的proto屬性。如果通過函式物件建立一個物件,那麼該物件的proto屬性就指向其建構函式的原型。
3、繼承
在講繼承之前,我們先來學習下屬性的查詢。在js中,其會按照原型鏈去查詢屬性,如果自己沒有,就根據proto屬性依次往上找。下面我們,先寫一段例項程式碼。

save.fileName = "oo"
save.prototype.fileName = "lili";
fileSave.fileName = "haha";

這裡寫圖片描述
這時我們如果列印fileSave.fileName的值,很明顯得到的是“haha”。但是如果我把fileSave.fileName = “haha”;去掉,再次列印會輸出什麼呢?
這裡寫圖片描述
從列印結果,我們知道會根據proto屬性中去找fileName屬性,即根據圖5的鏈圖去查詢需要的屬性。在這裡,如果沒有save.prototype.fileName = “lili”;這段賦值程式碼,打印出來的就是undefined,因為原型鏈中沒有對應的屬性。有人可能會說,為啥不會輸出“oo”,的確從程式碼中看到save.fileName = “oo”這段賦值程式碼,但是我們需要知道save是個函式物件,當執行這段程式碼時,finName會在constructor下,並不在原型中,類似於java中的靜態屬性(在這裡不能通過例項物件訪問)。
記住:通過普通物件呼叫屬性,該查詢只會在prototype的屬性中查詢,並不會在constructor中查詢。如果在save的原型中沒有找到,又會到save.proto中查詢,依次進行下去。
如果知道屬性查詢方式,那麼實現繼承就很簡單了。例如我們建立一個空物件saveDisk,如果我想訪問save中的fileName,我們只需要把saveDisk的proto的值等於save的原型即可(簡單理解為把兩條不相干的鐵鏈接在一起)。

saveDisk._proto_ = save.prototype

這裡寫圖片描述

總結:本文主要介紹了js中的原型鏈,以及利用原型鏈來實現繼承。以上只是個人理解,歡迎各位優秀的程式設計師點評。