摘要:所以,在每個構造函數都會有一個屬性,指向一個對象作為這個構造函數構造出來的新對象的原型。那么根據上面第二條事實,每個函數也會有指向它的構造函數的。而這個構造函數的函數就是,中的所有函數都是由構造出來的。
“__proto__”
JavaScript是一個面向對象語音,即一切皆對象。
那么怎么生成對象?在Java的世界里,對象是由類(Class)實例出來的,通俗地說,就是將事物抽象成一個模具,用這個模具(類)生產出一個個具體的實物(對象)。
可是JS中沒有類這個概念,有的是“原型”,對象是由原型衍生出來的。通俗地說,在JS的世界里,“原型”并不是一個模具,而是一個具體的實物(對象)。所有對象都是由另一個對象衍生出來的,而這個被衍生的對象就是所謂的“原型對象”。
每一個對象自動生成一個屬性:__proto__,這個屬性是一個引用對象,其指向這個對象的“原型對象”。
Talk is cheap, show me the code! 咱們來看看代碼:
var obj = {}; console.log(obj);
咱們將__proto__展開看看:是一些默認方法。
你一定會發生這個__proto__對象中也有一個__proto__對象,正如我們剛才說的,每個對象都有一個__proto__屬性指向它的原型對象。我們打印一下這個__proto__中的__proto__:
console.log(obj.__proto__.__proto__); //--> null
結果是null,說明已經到了頂層原型對象。obj是用大括號{}定義的,obj的原型對象自然是JS的頂層對象。
咱們再看一端代碼,加強下理解:
var parent = { name : "parent" }; var child = { name : "child", __proto__ : parent }; var subChild = { name : "subChild", __proto__ : child } console.log(subChild);
subChild.__proto__ --> child
child.__proto__ --> parent
parent.__proto__ --> 頂層原型對象
上面我們說到,每一個對象都包含一個__proto__,指向這個的對象的“原型”。
類似的事情是,每一個函數都包含一個prototype,這個prototype對象干什么的了?
咱們看看如下代碼,用構造函數來創建一個對象(上面是用字面量的形式創建對象)。
function Foo(){}; var foo = new Foo(); console.log(foo.__proto__);
試想想,這個foo對象的__proto__會指向什么?
一個包含constructor屬性的對象?看不太懂沒關系,把函數Foo的prototype屬性打印出來,對比一下就知道了。
function Foo(){}; var foo = new Foo(); console.log(foo.__proto__); console.log(Foo.prototype); console.log(foo.__proto__ === Foo.prototype);
原來,new出來的對象foo的__proto__就只指向函數Foo的prototype。
foo.__proto__ --> Foo.prototype
JS這么設計有何意義了?回憶下上面說的,在JS的世界中,對象不是根據類(模具)創建出來的,而是從原型(另一個對象)衍生出來的。
當我們執行new操作創建一個新的對象時,先不深入new操作的具體實現,但有一點我們是肯定的——就是為新對象的__proto__指向一個原型對象。
就剛才這段代碼
function Foo(){}; var foo = new Foo();
foo.__proto__到底要指向誰了?你怎么不能指向Foo這個函數本身吧,雖然函數也是對象,這個有機會會詳細講。但如何foo.__proto__指向Foo固然不合適,因為Foo是一個函數,有很多邏輯代碼,foo作為一個對象,繼承邏輯處理沒有任何意義,它要繼承的是“原型對象”的屬性。
所以,每個函數會自動生成一個prototype對象,由這個函數new出來的對象的__proto__就指向這個函數的prototype。
foo.__proto__ --> Foo.prototype
說了這么多,感覺還是沒完全說清楚,不如上一張圖。我曾經參考過其他網友的圖,但總覺得哪里沒說清楚,所以我自己畫了一張圖,如果覺得我的不錯,請點個贊!(老子可是費了牛勁才畫出來)。
(點擊可放大)
咱們就著這張圖,記住如下幾個事實:
1. 每個對象中都有一個_proto_屬性。
JS世界中沒有類(模具)的概念,對象是從另一個對象(原型)衍生出來的,所以每個對象中會有一個_proto_屬性指向它的原型對象。(參考左上角的那個用字面量形式定義的對象obj,它在內存中開辟了一個空間存放對象自身的屬性,同時生成一個_proto_指向它的原型——頂層原型對象。)
2. 每個函數都有一個prototype屬性。
“構造函數”為何叫構造函數,因為它要構造對象。那么根據上面第一條事實,構造出來的新對象的_proto_屬性指向誰了?總不能指向構造函數自身,雖然它也是個對象,但你不希望新對象繼承函數的屬性與方法吧。所以,在每個構造函數都會有一個prototype屬性,指向一個對象作為這個構造函數構造出來的新對象的原型。
3. 函數也是對象。
每個函數都有一些通用的屬性和方法,比如apply()/call()等。但這些通用的方法是如何繼承的呢?函數又是怎么創建出來的呢?試想想,一切皆對象,包括函數也是對象,而且是通過構造函數構造出來的對象。那么根據上面第二條事實,每個函數也會有_proto_指向它的構造函數的prototype。而這個構造函數的函數就是Function,JS中的所有函數都是由Function構造出來的。函數的通用屬性與方法就存放在Function.prototype這個原型對象上。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78272.html
摘要:實例可以通過代理來找到它,并用來檢測其構造函數。經典繼承圖這也是通過構造函數來創建對象,但是在這一系列的對象和實例之間我們的焦點是放在原型鏈上。盡管,但構造函數的屬性并不是對象自己的屬性,它實際上是通過尋找原型鏈獲得的,即所指向的地方。 繼承是面向對象編程語言的一大核心功能點,雖然JavaScript并不是一門真正意義上的面向對象的編程語言,但也通過某種手段實現了繼承這一功能,最常見的...
摘要:了解中原型以及原型鏈只需要記住以下點即可對象都有屬性,指向構造函數的構造函數函數都有屬性,指向構造函數的原型對象的內置構造函數可知所有的構造函數都繼承于甚至包括根構造器及自身。 了解JavaScript中原型以及原型鏈只需要記住以下2點即可 對象都有__proto__屬性,指向構造函數的prototype 構造函數函數都有prototype屬性,指向構造函數的原型 1、對象的__p...
摘要:而作為構造函數,需要有個屬性用來作為以該構造函數創造的實例的繼承。 歡迎來我的博客閱讀:「JavaScript 原型中的哲學思想」 記得當年初試前端的時候,學習JavaScript過程中,原型問題一直讓我疑惑許久,那時候捧著那本著名的紅皮書,看到有關原型的講解時,總是心存疑慮。 當在JavaScript世界中走過不少旅程之后,再次萌發起研究這部分知識的欲望,翻閱了不少書籍和資料,才搞懂...
摘要:深入理解原型與繼承看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習慣了面向對象編程的人來說更難理解,這里我就給大家說說我的理解。 深入理解:JavaScript原型與繼承 看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習慣了面向對象編程的人來說更難理解,這里我就給大家說說我的理解。 首先JavaScript是一門基于原型編程的語言...
摘要:原文鏈接關于的原型和原型鏈,看我就夠了一參考鏈接闖關記之原型及原型鏈之原型與原型鏈一篇文章帶你理解原型和原型鏈徹底理解原型鏈一的默認指向圖解和的三角關系原型和原型鏈三張圖搞懂的原型對象與原型鏈 溫故 創建對象的三種方式 通過對象直接量 通過new創建對象 通過Object.create() js中對象分為兩種 函數對象 普通對象 仔細觀察如下代碼 function Foo(na...
摘要:在創建對象不論是普通對象還是函數對象的時候,都有一個叫做的內置屬性,用于指向創建它的構造函數的原型對象,也就是。因為一個普通對象的構造函數所以原型鏈原型鏈的形成是真正是靠而非。參考文章最詳盡的原型與原型鏈終極詳解,沒有可能是。 【前端芝士樹】Javascript的原型、原型鏈以及繼承機制 前端的面試中經常會遇到這個問題,自己也是一直似懂非懂,趁這個機會整理一下 0. 為什么會出現原型和...
閱讀 1794·2021-11-18 10:02
閱讀 3524·2021-11-16 11:45
閱讀 1786·2021-09-10 10:51
閱讀 2106·2019-08-30 15:43
閱讀 1372·2019-08-30 11:23
閱讀 1484·2019-08-29 11:07
閱讀 1892·2019-08-23 17:05
閱讀 1394·2019-08-23 16:14