1. 程式人生 > >一張圖讓你搞懂JavaScript的繼承與原型鏈

一張圖讓你搞懂JavaScript的繼承與原型鏈

前面的話

  javascript裡的關係又多又亂。作用域鏈是一種單向的鏈式關係,還算簡單清晰;this機制的呼叫關係,稍微有些複雜;而關於原型,則是prototype、proto和constructor的三角關係。本文先用一張圖開宗明義,然後詳細解釋原型的三角關係

這裡寫圖片描述

概念

上圖中的複雜關係,實際上來源就兩行程式碼

function Foo(){};
var f1 = new Foo;

【建構函式】

  用來初始化新建立的物件的函式是建構函式。在例子中,Foo()函式是建構函式

【例項物件】

  通過建構函式的new操作建立的物件是例項物件。可以用一個建構函式,構造多個例項物件

function Foo(){};
var f1 = new Foo;
var f2 = new Foo;
console.log(f1 === f2);//false


【原型物件及prototype】

  建構函式有一個prototype屬性,指向例項物件的原型物件。通過同一個建構函式例項化的多個物件具有相同的原型物件。經常使用原型物件來實現繼承

function Foo(){};
Foo.prototype.a = 1;
var f1 = new Foo;
var f2 = new Foo;
console.log(Foo.prototype.a);//1
console.log(f1.a);//1
console.log(f2.a);//1

【constructor】

  原型物件有一個constructor屬性,指向該原型物件對應的建構函式

function Foo(){};
console.log(Foo.prototype.constructor === Foo);//true


  由於例項物件可以繼承原型物件的屬性,所以例項物件也擁有constructor屬性,同樣指向原型物件對應的建構函式

function Foo(){};
var f1 = new Foo;
console.log(f1.constructor === Foo);//true

【proto】

  例項物件有一個proto屬性,指向該例項物件對應的原型物件

function Foo(){};
var f1 = new Foo;
console.log(f1.__proto__ === Foo.prototype);//true

  概念介紹完了,現在對圖示的關係進行詳細說明



function Foo(){};
var f1 = new Foo;

【第一部分: Foo】
這裡寫圖片描述

  例項物件f1是通過建構函式Foo()的new操作建立的。建構函式Foo()的原型物件是Foo.prototype;例項物件f1通過proto屬性也指向原型物件Foo.prototype

function Foo(){};
var f1 = new Foo;
console.log(f1.__proto === Foo.prototype);//true

  例項物件f1本身並沒有constructor屬性,但它可以繼承原型物件Foo.prototype的constructor屬性

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true
console.log(f1.hasOwnProperty('constructor'));//false

  下圖是例項物件f1的控制檯效果
這裡寫圖片描述

【第二部分: Object】
這裡寫圖片描述

  Foo.prototype是f1的原型物件,同時它也是例項物件。實際上,任何物件都可以看做是通過Object()建構函式的new操作例項化的物件
  所以,Foo.prototype作為例項物件,它的建構函式是Object(),原型物件是Object.prototype。相應地,建構函式Object()的prototype屬性指向原型物件Object.prototype;例項物件Foo.prototype的proto屬性同樣指向原型物件Object.prototype

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.__proto__ === Object.prototype);//true

  例項物件Foo.prototype本身具有constructor屬性,所以它會覆蓋繼承自原型物件Object.prototype的constructor屬性

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.constructor === Foo);//true
console.log(Object.prototype.constructor === Object);//true
console.log(Foo.prototype.hasOwnProperty('constructor'));//true

  下圖是例項物件Foo.prototype的控制檯效果
這裡寫圖片描述

  如果Object.prototype作為例項物件的話,其原型物件是什麼,結果是null。私以為,這可能也是typeof null的結果是’object’的原因之一吧

console.log(Object.prototype.__proto__ === null);//true

【第三部分: Function】
這裡寫圖片描述

  前面已經介紹過,函式也是物件,只不過是具有特殊功能的物件而已。任何函式都可以看做是通過Function()建構函式的new操作例項化的結果

  如果把函式Foo當成例項物件的話,其建構函式是Function(),其原型物件是Function.prototype;類似地,函式Object的建構函式也是Function(),其原型物件是Function.prototype

function Foo(){};
var f1 = new Foo;
console.log(Foo.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.prototype);//true

  原型物件Function.prototype的constructor屬性指向建構函式Function();例項物件Object和Foo本身沒有constructor屬性,需要繼承原型物件Function.prototype的constructor屬性

function Foo(){};
var f1 = new Foo;
console.log(Function.prototype.constructor === Function);//true
console.log(Foo.constructor === Function);//true
console.log(Foo.hasOwnProperty('constructor'));//false
console.log(Object.constructor === Function);//true
console.log(Object.hasOwnProperty('constructor'));//false

  所有的函式都可以看成是建構函式Function()的new操作的例項化物件。那麼,Function可以看成是呼叫其自身的new操作的例項化的結果

  所以,如果Function作為例項物件,其建構函式是Function,其原型物件是Function.prototype

console.log(Function.__proto__ === Function.prototype);//true
console.log(Function.prototype.constructor === Function);//true
console.log(Function.prototype === Function.prototype);//true

  如果Function.prototype作為例項物件的話,其原型物件是什麼呢?和前面一樣,所有的物件都可以看成是Object()建構函式的new操作的例項化結果。所以,Function.prototype的原型物件是Object.prototype,其原型函式是Object()

console.log(Function.prototype.__proto__ === Object.prototype);//true

  第二部分介紹過,Object.prototype的原型物件是null

console.log(Object.prototype.__proto__ === null);//true

總結

  【1】函式(Function也是函式)是new Function的結果,所以函式可以作為例項物件,其建構函式是Function(),原型物件是Function.prototype

  【2】物件(函式也是物件)是new Object的結果,所以物件可以作為例項物件,其建構函式是Object(),原型物件是Object.prototype

  【3】Object.prototype的原型物件是null

相關推薦

JavaScript繼承原型

前面的話   javascript裡的關係又多又亂。作用域鏈是一種單向的鏈式關係,還算簡單清晰;this機制的呼叫關係,稍微有些複雜;而關於原型,則是prototype、proto和constructor的三角關係。本文先用一張圖開宗明義,然後詳細解釋原型的三

輕松javascript event對象的clientX,offsetX,screenX,pageX區別

png javascrip 區域 文檔 .cn 標準屬性 分享 clas src 先總結下區別: event.clientX、event.clientY 鼠標相對於瀏覽器窗口可視區域的X,Y坐標(窗口坐標),可視區域不包括工具欄和滾動條。IE事件和標準事件都定義了這2

Spring @Scheduled定時任務的fixedRate,fixedDelay,cron執行差異

https://blog.csdn.net/applebomb/article/details/52400154   看字面意思容易理解,但是任務執行長度超過週期會怎樣呢? 不多說,直接上圖: 測試程式碼: import java.text.DateFormat; imp

了區塊再去挖礦,看明白怎麼回事

  今年簡單就是區塊鏈爆發的一年,每天開啟媒體資訊都會看到各式的區塊鏈產品出現在你的面前。而且有好多粉絲諮詢我區塊鏈產品的問題,我都是以私人回覆的形式回答的。 既然這麼多人追捧對區塊鏈感興趣,今天就單獨用一

4分布式架構從硬件到軟件

開發 基本 行處理 倉庫 tcp -1 管理 img 必須 對於分布式的架構相對很多開發者都是個高大上的項目,其實只要看得懂圖精通tcp通信、精通磁盤管理、精通內存管理、精通多線程與並行處理,精通事務(其實事務就是基於tcp通信層所擴展而來的MQ之類的一種IO消息模式而與)

徹底理解js原型

function Person() { this.name = 'sanlyshi'; this.age = '23'; this.eat = function () { console.log(this.name +' is eating!')

Java的八種基本資料型別

String和Integer不是Java的八種基本資料型別。char只能儲存一個字元(用單引號),String能夠儲存多個字元(用雙引號)。String屬於final類,定義的是物件,Integer 是 java 為 int 提供的封裝類。int 的預設值為 0,

PMP專案管理的49個過程,全部瞭解

專案管理的49個過程,看錶格顯得比較單調,印象也不是很深,所以今天小編就給大家發一張圖片,可以用一張圖就能生動又詳細的瞭解PMP專案管理的49個過程。   大家看完是不是覺得一目瞭然了呢,圖片上傳後不知道是不是清楚,大家覺得不清楚的可以

清晰前端入門到底需要學什麼

很多0基礎或者已經工作一兩年的程式設計師,都有一個“期望”,想得到一份學習計劃,知道什麼時間該學什麼東西, 想系統的、全面的精進一下技術。 今天我們就重點聊一下,關於如何科學合理的制定一份javascript學習計劃,提升自己js技能這件事。 第一個問題:為什麼這麼

掌握Python所有基礎知識,Python入門足矣!

  今天用一張思維導圖彙總了Python基礎知識,與大家分享。第一張圖為總圖,之後為總圖的區域性。   總圖   區域性1   區域性2   結語 當然這只是基礎的入門階段,後續學

自學程式設計?別傻了!認清自己和科班程式設計師的差別!

自學程式設計和科班程式設計師的差別到底有多大?這也是即將“入坑”的程式設計愛好者,最關心的一個問題。自學和科班最大的差距還是在上車有沒有車票的問題,是起跑線的問題。至於上了車,那就真的是各顯神通了。 知識體系的差別 科班出身的程式設計師,相對於自學程式設計者,具備更加完善的知識體系,在實際工

25神經網路架構

25張圖讓你讀懂神經網路架構 轉載自CSDN部落格 Nicholas_Liu2017 原部落格網址:http://blog.csdn.net/nicholas_liu2017/article/details/73694666 由於新的神經網路架構無時無刻不在湧現,想要記錄所有的

學會Python,學習Python的簡單,小白的福利

網上有這樣一張圖片,資訊量很大,通常會被配上標題“一張圖讓你學會Python”: 點選圖片可檢視大圖     這張圖流傳甚廣,但我沒有找到明確的出處,圖片上附帶了 UliPad 的作者 Limodou 的資訊,很有可能是原作者。如有知情者可留言告訴我。

瞭解Storm的DRPC實現原理

參照上圖 構建DRPC拓補圖的拓補構造器: package backtype.storm.drpc; import backtype.storm.Constants; import backtype.storm.ILocalDRPC; import backtype.s

詳細理解Group By的分組聚合過程

Group By分組聚合是我們在使用過程中使用最多的SQL之一(另外一個使用最多的估計就是JOIN了吧),為了讓大家詳細瞭解Group By的計算執行過程,我們下面使用一張圖來詳細講解一下。

阿里P8Java大牛僅用46JVM的體系結構GC調優。

本PPT從JVM體系結構概述、GC演算法、Hotspot記憶體管理、Hotspot垃圾回收器、調優和監控工具六大方面進行講述。圖文

篇文章原型原型

本文由葡萄城技術團隊原創並首發 轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。   與多數面向物件的開發語言有所不同,雖然JavaScript沒有引入類似類的概念(ES6已經引入了class語法糖),但它仍然能夠大量的使用物件,那麼如何將所有物件聯絡起

我畫了 40 就是為了計算機網路層

> 我把自己以往的文章彙總成為了 Github ,歡迎各位大佬 star > https://github.com/crisxuan/bestJavaer ![](https://s3.ax1x.com/2021/01/03/spO8e0.png) 前面我們學習了運輸層如何為客戶端和伺服器輸送資料的,提

8步步看清 async/await 和 promise 的執行順序

原文:8張圖幫你一步步看清 async/await 和 promise 的執行順序 作者:ziwei3749 Fundebug經授權轉載,版權歸原作者所有。 為什麼寫這篇文章? 說實話,關於js的非同步執行順序,巨集任務、微任務這些,或者async/await這些慨念已經有非常多的文章寫了

1分鐘python中的編碼!專門給小白寫的篇文章

很多初學者會被Python中UnicodeDecodeError弄得一頭汙水,相信你也一定遇到過這個問題,這裡我們講一下編碼相關的知識。 (部分內容參考了 《編寫高質量Python程式碼的59個有效方法》一書 ) 1. 原理: 加群943752371即可獲取十套PDF和