一張圖理解JS的原型(prototype、_proto_、constructor的三角關系)

注意:前方高能預警,請認真仔細看完,閱讀完后自己再次畫下原型圖,相信你一定會有更深刻的認識。(推薦炒雞好用的畫流程圖的軟件ProcessOn)

構造函數:function Foo ( ) { };

實例對象:let f1=new Foo;

let o1=new Foo;

每個函數都有 prototype 屬性,除了 Function.prototype.bind(),該屬性指向原型

每個對象都有 __proto__ 屬性指向了創建該對象的構造函數的原型。其實這個屬性指向了 [[prototype]],但是 [[prototype]] 是內部屬性,我們并不能訪問到,所以使用 _proto_ 來訪問。

對象可以通過 __proto__ 來尋找不屬于該對象的屬性,__proto__ 將對象連接起來組成了原型鏈。

?

下面我們來解釋上圖的原型圖的含義:

概念:

1、構造函數:用來初始化新創建的對象的函數是構造函數。在例子中,Foo()函數是構造函數。

2、實例對象:通過構造函數的new操作創建的對象是實例對象。可以用一個構造函數,構造多個實例對象。

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

3、原型對象及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復制代碼

4、constructor:原型對象有一個constructor屬性,指向該原型對象對應的構造函數。由于實例對象可以繼承原型對象的屬性,所以實例對象也擁有constructor屬性,同樣指向原型對象對應的構造函數。

console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true復制代碼

5、_proto_:實例對象有一個proto屬性,指向該實例對象對應的原型對象。

console.log(f1.__proto__ === Foo.prototype);//true復制代碼

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

【第一部分: Foo】

?

1、實例對象f1是通過構造函數Foo()的new操作創建的。構造函數Foo()的原型對象是Foo.prototype;實例對象f1通過__proto__屬性也指向原型對象Foo.prototype。

console.log(f1.__proto === Foo.prototype);//true
復制代碼

2、實例對象f1本身并沒有constructor屬性,但它可以繼承原型對象Foo.prototype的constructor屬性

console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true
console.log(f1.hasOwnProperty('constructor'));//false復制代碼

  下圖是實例對象f1的控制臺效果

?

【第二部分: Object】

?

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

console.log(Foo.prototype.__proto__ === Object.prototype);//true
復制代碼

2、實例對象Foo.prototype本身具有constructor屬性,所以它會覆蓋繼承自原型對象Object.prototype的constructor屬性。

console.log(Foo.prototype.constructor === Foo);//true
console.log(Object.prototype.constructor === Object);//true
console.log(Foo.prototype.hasOwnProperty('constructor'));//true復制代碼

  下圖是實例對象Foo.prototype的控制臺效果

?

3、如果Object.prototype作為實例對象的話,其原型對象是什么,結果是null。我以為,這可能也是typeof null的結果是'object'的原因之一吧。

console.log(Object.prototype.__proto__ === null);//true
復制代碼

【第三部分: Function】

?

1、前面已經介紹過,函數也是對象,只不過是具有特殊功能的對象而已。任何函數都可以看做是通過Function()構造函數的new操作實例化的結果。如果把函數Foo當成實例對象的話,其構造函數是Function(),其原型對象是Function.prototype;類似地,函數Object的構造函數也是Function(),其原型對象是Function.prototype。

console.log(Foo.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.prototype);//true復制代碼

2、原型對象Function.prototype的constructor屬性指向構造函數Function();實例對象Object和Foo本身沒有constructor屬性,需要繼承原型對象Function.prototype的constructor屬性。

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
復制代碼

3、所有的函數都可以看成是構造函數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復制代碼

4、如果Function.prototype作為實例對象的話,其原型對象是什么呢?和前面一樣,所有的對象都可以看成是Object()構造函數的new操作的實例化結果。所以,Function.prototype的原型對象是Object.prototype,其原型函數是Object()。

console.log(Function.prototype.__proto__ === Object.prototype);//true
復制代碼

總結:

【1】函數(Function也是函數)是new Function的結果,所以函數可以作為實例對象,其構造函數是Function(),原型對象是Function.prototype。

【2】對象(函數也是對象)是new Object的結果,所以對象可以作為實例對象,其構造函數是Object(),原型對象是Object.prototype

【3】Object.prototype的原型對象是null。



本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/538029.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538029.shtml
英文地址,請注明出處:http://en.pswp.cn/news/538029.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Oracle觸發器和MySQL觸發器之間的區別

原文鏈接:http://blog.csdn.net/a19881029/article/details/37820363 -----------------------------------------------------------Oracle觸發器格式:[plain] view plaincopyCREATE [OR REPLACE] TRIGGER trigger_name BEFORE|AFTER INSERT|UPDA…

下列選項中不符合python語言變量命名規則的是_學習Python第二日--基本概念和類型...

編程語言分類:解釋型語言和編譯型語言。解釋型語言不會產生額外的文件,運行時一行一行的翻譯。編譯型語言需要產生一個額外的文件,是電腦能夠識別的內容,運行后將產生額外的文件。 變量是可變的量,是它的值可以發生改變。變量的作用是保存值,保存的值可以是數據,而且保存…

HashMap死鎖原因及替代方案

原文鏈接:http://blog.csdn.net/fhzaitian/article/details/51505516 ------------------------------------------------------------------------1、首先我們需要簡單地了解一下HashMap數據結構 HashMap通常會用一個指針數組(假設為table[]&#xff09…

優化mysql數據庫_MySQL數據庫十大優化技巧

WEB開發者不光要解決程序的效率問題,對數據庫的快速訪問和相應也是一個大問題。希望本文能對大家掌握MySQL優化技巧有所幫助。1. 優化你的MySQL查詢緩存在MySQL服務器上進行查詢,可以啟用高速查詢緩存。讓數據庫引擎在后臺悄悄的處理是提高性能的最有效方…

跋山涉水——深入 Redis 字典遍歷

Redis 字典的遍歷過程邏輯比較復雜,互聯網上對這一塊的分析講解非常少。我也花了不少時間對源碼的細節進行了整理,將我個人對字典遍歷邏輯的理解呈現給各位讀者。也許讀者們對字典的遍歷過程有比我更好的理解,還請不吝指教。一邊遍歷一邊修改…

linux下VI模式中上下左右鍵和回退鍵出現字母

原文地址:http://blog.csdn.net/u012860950/article/details/50127779 ---------------------------------------------------------------- 1.編輯/etc/vim/vimrc.tiny 由于/etc/vim/vimrc.tiny的擁有者是root用戶,所以要在root的權限下對這個文件進行修…

mysql數據庫查詢優化建議_mysql數據庫查詢優化的24條建議

MySQL是一個強大的開源數據庫。隨著MySQL上的應用越來越多,MySQL逐漸遇到了瓶頸。這里提供一些關于Mysql 數據庫查詢優化的24條優化建議,僅供參考。Mysql 查詢優化1、使用慢查詢日志,找出執行慢的查詢。2、使用 EXPLAIN 來決定查詢功能是否合…

常規sql讀取CLOB

plsql下,普通sqlsql-cmd下總結: 常規的sql,查詢clob字段,只能顯示部分內容。 查clob內容select dbms_lob.substr(c_content) from table_content t dbms_lob.substr將大文本轉換字符類型讀出來.dbms_lob.substr的轉換對字段conten…

精解 ES6箭頭函數

🐱 個人主頁:SHOW科技,公眾號:SHOW科技 🙋?♂? 作者簡介:2020參加工作,專注于前端各領域技術,共同學習共同進步,一起加油呀! 💫優質專欄&#x…

硬盤主引導記錄詳解

說明:硬盤主引導記錄獨立于操作系統,但又和操作系統息息相關——很多時候它又是由; 操作系統所提供的工具所生成(例外的情況是您使用了其他的分區工具,不過它又運行在; 什么操作系統中呢?;()。;; 如果您安裝…

Oracle char varchar varchar2 nvarchar2 的區別

上面字符類型能保存多少個字符與oracle當前的字符集有關系。 select userenv(language) from dual; 假設長度2000字節, 如果字符集是16位編碼的,ZHS16GBK,那么每個字符16位,2字節,所以可以容納1000字符。 如果是32位編…

樹莓派lnmp安裝mysql_在樹莓派上安裝 LNMP

樹莓派支持安裝非常多的操作系統,如官方所展示:這里我選擇了推薦的 Raspbian 系統,它基于 Debian,這就意味著我可以按照 Debian 的方式來安裝軟件。一、安裝 Nginx0、先將系統更新到最新狀態$ sudo apt-get update && sud…

openlayers5之熱力圖heatmap

版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/gisdoer/article/details/81745645 openlayers5之熱力圖 點擊查看文章

maven項目在打war包時出現非法字符: '\ufeff' 解決方案

http://blog.csdn.net/qi_fei/article/details/61416319 --------------------------------------------問題描述: 開發工具MyEclipse 的總體開發環境,編碼格式總體設置為UTF-8,在將web項目打包的時候出現:非法字符:\u…

0027-生成圓

題目 生成圓難度級別:A; 運行時間限制:1000ms; 運行空間限制:51200KB; 代碼長度限制:2000000B 試題描述給你一些特殊的圓,每個這樣的圓每秒可以產生一個普通的圓,如果給你…

mysql啟多_MySQL啟多個實例

很多朋友都想在一臺服務器上運行多個MySQL Instance,究竟怎么做呢?首先要明晰幾個原理, 簡稱為mysqld讀取my.cnf的順序:第一搜,首先讀取/etc/my.cnf,多實例這個配置文件不會存在。:-(第二搜&…

數據連接池druid 和 大數據框架druid

叫druid的有兩個開源項目。 一個是:Druid是一個JDBC組件,它包括三部分: DruidDriver 代理Driver,能夠提供基于Filter-Chain模式的插件體系。 DruidDataSource 高效可管理的數據庫連接池。 SQLParser 另一個是&#xff…

零基礎入門深度學習(5) - 循環神經網絡

往期回顧 在前面的文章系列文章中,我們介紹了全連接神經網絡和卷積神經網絡,以及它們的訓練和使用。他們都只能單獨的取處理一個個的輸入,前一個輸入和后一個輸入是完全沒有關系的。但是,某些任務需要能夠更好的處理序列的信息&am…

sql排名名次分頁mysql_mysql 實現排名及中文排序實例[分頁累加行號]

/*排名相同情況下,優先按姓名排序*/SELECT t.name, t.company_name, rownum:rownum1 as rankNum, t.ss from (SELECT u.name, sci.company_name, rownum:0,(u.check_numu.online_hours) as ss FROM v_user uLEFT JOIN sys_company_info sci ON u.companyId sci.com…

世上最簡單的mysql_史上最簡單安裝MySQL教程

1.安裝MySQL很多都推薦在MySQL官網進行安裝,我剛開始試的時候官網下載zip文件,打開完全找不到,踩坑了后面我發現了Windows簡易安裝,俗稱傻子都會安裝安裝好了就會看到一個這個文件安裝之前首先你的有沒有這個你就無法安裝,這個可以去這里進行下載安裝好了就可以安裝MySQL了因為…