js中關於原型鏈與繼承的理解
js中的原型鍊是比較難理解的部分知識,而繼承又是依賴原型鏈,所以原型鍊是我們必須去掌握的。在學習原型鏈之前,我們需要先去介紹一下原型。建議這部分重在理解,不建議死記硬背。
1、原型
js中只有函數物件才有原型,原型也是物件。例如,我們建立一個save函數,透過typeof來查看其類型,傳回值是”object”,說明其實一個物件。
#
圖1 函數中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中關於原型鏈與繼承的理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

在函數繼承中,使用「基底類別指標」和「衍生類別指標」來理解繼承機制:基底類別指標指向派生類別物件時,執行向上轉型,只存取基底類別成員。派生類別指標指向基底類別物件時,執行向下轉型(不安全),必須謹慎使用。

繼承和多態性會影響類別的耦合度:繼承會增加耦合度,因為衍生類別依賴基底類別。多態性可以降低耦合度,因為物件可以透過虛擬函數和基底類別指標以一致的方式回應訊息。最佳實踐包括謹慎使用繼承、定義公共介面、避免在基底類別中新增資料成員,以及透過依賴注入解耦類別。實戰案例顯示如何使用多態性和依賴注入來降低銀行帳戶應用程式中的耦合度。

繼承錯誤調試技巧:確保正確的繼承關係。使用偵錯器逐步執行程式碼,檢查變數值。確保正確使用virtual修飾符。檢查隱藏的繼承帶來的菱形繼承問題。檢查抽象類別中未實現的純虛函數。

C++函式繼承詳解:掌握「is-a」和「has-a」關係什麼是函式繼承?函數繼承是C++中一種將衍生類別中定義的方法與基底類別中定義的方法關聯起來的技術。它允許衍生類別存取和重寫基底類別的方法,從而擴展了基底類別的功能。 「is-a」和「has-a」關係在函數繼承中,「is-a」關係指派生類別是基底類別的子類型,也就是說,衍生類別「繼承」了基底類別的特性和行為。 「has-a」關係指派生類別包含對基底類別物件的參考或指針,也就是說,衍生類別「擁有」了基底類別物件。語法以下是如何實作函數繼承的語法:classDerivedClass:pu

什麼是物件導向程式設計?物件導向程式設計(OOP)是一種程式設計範式,它將現實世界中的實體抽象化為類,並使用物件來表示這些實體。類別定義了物件的屬性和行為,而物件則實例化了類別。 OOP的主要優點在於它可以使程式碼更易於理解、維護和重複使用。 OOP的基本概念OOP的主要概念包括類別、物件、屬性和方法。類別是物件的藍圖,它定義了物件的屬性和行為。物件是類別的實例,它具有類別的所有屬性和行為。屬性是物件的特徵,它可以儲存資料。方法是物件的函數,它可以對物件的資料進行操作。 OOP的優點OOP的主要優點包括:可重複使用性:OOP可以讓程式碼更

在以下情況下不應使用C++函數繼承:衍生類別需要不同實作時,應建立具有不同實作的新函數。衍生類別不需要函數時,應宣告為一個空類別或使用私有、未實作的基底類別成員函數來停用函數繼承。函數不需要繼承時,應使用其他機制(例如範本)來實作程式碼重用。

介面:無實作的契約介面在Java中定義了一組方法簽名,但不提供任何具體實作。它充當一種契約,強制實作該介面的類別實現其指定的方法。介面中的方法是抽象方法,沒有方法體。程式碼範例:publicinterfaceAnimal{voideat();voidsleep();}抽象類別:部分實作的藍圖抽象類別是一種父類,它提供了一個部分實現,可以被它的子類別繼承。與介面不同,抽象類別可以包含具體的實作和抽象方法。抽象方法是用abstract關鍵字聲明的,並且必須被子類別覆蓋。程式碼範例:publicabstractcla

深入理解Linux管道的使用方法在Linux作業系統中,管道是一種非常有用的功能,能夠將一個命令的輸出作為另一個命令的輸入,從而方便地實現各種複雜的資料處理和操作。深入理解Linux管道的使用方法對於系統管理員和開發人員來說非常重要。本文將介紹管道的基本概念,並透過具體的程式碼範例來展示如何使用Linux管道進行資料處理和操作。 1.管道的基本概念在Linux
