prototype、proto和constructor的三角關係

来源:http://www.cnblogs.com/wei-hj/archive/2017/11/18/7856735.html
-Advertisement-
Play Games

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


前面的話

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

原文 https://www.cnblogs.com/xiaohuochai/p/5721552.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <style> body{ text-align:center} div{ margin:50px auto}</style><script type="text/javascript"> function clik(t){ //獲取所有的img標簽 var imgs = document.getE ...
  • 剛入園,以此來記錄有關學習html過程中的問題和理解。零基礎,現在在看教學視頻,剛看完html5.問題不大,作為前端開發最基礎的一塊,大致內容也就是記一些符號分別表示什麼。期間有一個問題就是,直接複製粘貼有時候行不通哦,代碼還是得自己一個一個敲啊,不要想著省事。記得之前是複製粘貼了一段話,而沒有那個 ...
  • 我發現現在很多網站都使用了這種效果,比如說錘子官網、elementui官網、秒味課堂等,不單單有滑鼠跟隨的效果,隨著滑鼠的移動還有視覺差的效果,看起來很高大上的技術,其實實現起來很簡單,主要利用css3的transform-style和persperctive屬性。 廢話不多說直接上代碼: html ...
  • 我兩年的web開發生涯 與以前的文章分享給大家自己的知識和觀點不同,這篇文章更多的是寫給自己的總結。 現在是 2017年10月18. 從 2015年9月 開始接觸前端開發,至今兩年零一個月。 從 2016年3月 入職中油瑞飛從事相關工作,至今一年零七個月。 目前我即將離職,並於下個月加入一點資訊。 ...
  • 以前學習使用vue,axios以及fetch去連接一個介面時遇到一些問題,這些問題都已經解決了,拿出來和大家分享一下。 1、搭建基本項目 http://blog.csdn.net/Small_Lee/article/details/68062223 2、安裝mint ui,vuex npm inst ...
  • 一個是前面提到的可以讀取函數內部的變數,另一個就是讓這些變數的值始終保持在記憶體中。 ...
  • 在閱讀一本HTML5游戲開發相關書籍時發現一個很好的例子,通過這個例子可以對面向對象的開發進行更深入的理解。這個對象要實現的是:將一個CSS sprite中的圖像繪製到canvas中。首先創建一個SpriteSheet對象,代碼如下: var SpriteSheet = new function() ...
  • 隨著互聯網的深入發展,前端開發工程師一躍成為市場上非常搶手的人才。很多同學,包括以前做UI的、Java的、或者對於IT完全零基礎的同學都想學習前端。下圖是網上流傳甚廣的一張前端學習思維導圖,很多初學者表示看到這些密密麻麻的知識點就已經暈了。確實,前端是一門涵蓋面很廣的學科。但是想學前端的你也不用慌張 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...