摘要:構造函數(shù)和實例都通過屬性指向了原形。代碼示例是構造函數(shù)的實例的屬性與的屬性保存的值相等,即他們指向同一個對象原形。
講清楚之javascript原型
標簽: javascript
javascript 中原形是一個比較難于理解的概念。javascript 權威指南在原形這一章也花了大量的篇幅進行介紹,也許你已經(jīng)讀過javascript 權威指南,或者已經(jīng)是讀第N篇了,然而這篇文章的目的就是在讀完之后,刨去細枝末節(jié)用幾分鐘梳理一下知識脈絡。
什么是原型?在 javascript 中原形是一個對象,通過原形可以實現(xiàn)屬性的繼承。
let personBase = new Object() personBase.gender = "男" let animal = { eyeNumber: 2 } let time = function () { let timeType = "seconds" }
上面創(chuàng)建了三個對象,他們可以作為任何函數(shù)的原形。
function Person (age) { this.age = age } Person.prototype = personBase let tom = new Person(18) console.log(tom.age) // 18 console.log(tom.gender) // "男"
personBase 是 Person的原形。 所以構造函數(shù)Person從personBase繼承了gender屬性
原形: 每一個 JavaScript 對象(假設為A,null除外)在創(chuàng)建的時候就會與之關聯(lián)另一個對象,這個對象就是我們所說的原型,每一個對象都會從原型"繼承"屬性。
A,在大多數(shù)編碼情景中可能是函數(shù)。函數(shù)默認都繼承于Function, 即Function默認是所有函數(shù)的原形。當我們通過prototype屬性給函數(shù)添加一個原形對象時,該原形對象會添加到原形鏈的近端。當然A也可以是其他數(shù)據(jù)類型(Number、String、Array、Boolean),例如 Number 類型,當我們通過字面量方式(var a = 1)初始化變量等同于通過構造函數(shù)方式實例化一個變量(var a = new Number(1)),即字面量方式創(chuàng)建的變量同樣是Number的實例。所以我們可以通過Number的prototype屬性來實現(xiàn)屬性和方法的繼承。(當然不建議這么做)構造函數(shù)、實例、原型之間的關系
弄明白這三者之間的關系關鍵是理解 prototype、__proto__、constructor 之間的的聯(lián)系:
屬性 | - |
---|---|
prototype | 函數(shù)屬性,指向原型 |
__proto__ | 實例屬性,指向原型 |
constructor | 原型屬性,指向構造函數(shù) |
在JavaScript中,每個函數(shù)都有一個prototype屬性,當一個函數(shù)被用作構造函數(shù)來創(chuàng)建實例時,該函數(shù)的prototype屬性值將被作為原型賦值給所有對象實例(設置實例的__proto__屬性),也就是說,所有實例的原型引用的是構造函數(shù)的prototype屬性。同時在原型對象中,包含一個"constructor"屬性,這個屬性對應創(chuàng)建所有指向該原型的實例的構造函數(shù)(有點拗口,就是constructor屬性指向構造函數(shù))。這三者的關系可以用下面的示例圖表示:
所以構造函數(shù)通過 prototype 屬性指向自己的原型。 構造函數(shù)的實例在創(chuàng)建后通過 __proto__ 屬性指向構造函數(shù)的 prototype 的對象,即實例函數(shù)也指向原型。構造函數(shù)和實例都通過屬性指向了原形。
代碼示例:
function Person () {} let manPerson = new Person() manPerson.__proto__ === Person.prototype // true Person.prototype.constructor === Person // true manPerson.constructor === Person.prototype.constructor // true
manPerson是構造函數(shù)Person的實例
manPerson的__proto__屬性與Person的prototype屬性保存的值相等,即他們指向同一個對象原形。
Person 的原形(Person.prototype)通過constructor屬性指向 構造函數(shù) Person ,即 Person和他的原形實現(xiàn)了相互引用
實例的constructor屬性與原形的constructor屬性相等。這里實例的constructor屬性是繼承自原形的constructor屬性。
反過來原型和構造函數(shù)是沒有指向?qū)嵗囊?,因為一個構造函數(shù)會有N個實例。javascript通過實例的 __proto__ 屬性來訪問共同的原形。
所有函數(shù)都是 Function 構造函數(shù)的實例,而且函數(shù)也是一個對象
同時函數(shù)實例的字面量方式創(chuàng)建 function too(){} 等同于構造函數(shù)方式創(chuàng)建 let foo = new Function()
foo instanceof Function // true too instanceof Function // true foo.__proto__ === too.__proto__ // true foo.__proto__ === Function.prototype // true foo是Function的實例
所以too、foo都是Function的實例,他們的_proto__指向的是Function構造函數(shù)的原型。
通過上面的示例代碼分析,這里主要涉及到 prototype 、__proto__、constructor 這3個屬性的關系。
我們再次梳理一下:
對于所有的對象,都有__proto__屬性,這個屬性對應該對象的原型
對于函數(shù)對象,除了__proto__屬性之外,還有prototype屬性,當一個函數(shù)被用作構造函數(shù)來創(chuàng)建實例時,該函數(shù)的prototype屬性值將被作為原型賦值給所有對象實例(也就是設置實例的__proto__屬性)
所有的原型對象都有constructor屬性,該屬性對應創(chuàng)建所有指向該原型的實例的構造函數(shù)
函數(shù)對象和原型對象通過prototype和constructor屬性進行相互關聯(lián)
所以上面的關系圖其實可以于理解為:
題外話:
Function.prototype === Function.__proto__
先有雞還是先有蛋?怎么 Function 作為構造函數(shù) 與 Function 作為實例對象的原型相等
在JavaScript中,F(xiàn)unction構造函數(shù)本身也算是Function類型的實例嗎?Function構造函數(shù)的prototype屬性和__proto__屬性都指向同一個原型,是否可以說Function對象是由Function構造函數(shù)創(chuàng)建的一個實例?
相關問題
JavaScript 里 Function 也算一種基本類型?
在JavaScript中,F(xiàn)unction構造函數(shù)本身也算是Function類型的實例嗎?
對于這類問題也可以不用深究。
constructor原型的constructor屬性指向?qū)臉嬙旌瘮?shù)
function Person() { } console.log(Person === Person.prototype.constructor); // true原型鏈
當理解了原形的概念后,原形鏈就比較好理解了。
因為每個對象和原型都有原型,對象的原型指向?qū)ο蟮母福傅脑陀种赶蚋傅母?,這種原型層層連接起來的就構成了原型鏈。.JavaScript 對象通過__proto__指向原型對象的鏈。原形鏈的概念不難理解,當訪問一個對象的屬性時,它不僅僅在該對象上搜尋,還會搜尋該對象的原型,以及該對象的原型的原型,依次層層向上搜索,直到找到一個名字匹配的屬性或到達原型鏈的末尾,找到就返回該屬性的值否則就返回undefind(原形鏈的末端是 null)。
關于 javascript 中各數(shù)據(jù)類型原形之間的關系可以參考下圖理解:
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/95224.html
摘要:講清楚之中的這一節(jié)來探討。所以當函數(shù)作為構造函數(shù)調(diào)用,則函數(shù)內(nèi)部的綁定到該函數(shù)上。在通過構造函數(shù)實例化對象時,對象內(nèi)部的也同樣指向該實例對象。 講清楚之 javascript中的this 這一節(jié)來探討this。 在 javascript 中 this 也是一個神的存在,相對于 java 等語言在編譯階段確定,而在 javascript 中, this 是動態(tài)綁定,也就是在運行期綁定的。...
摘要:工廠函數(shù)創(chuàng)建實例同時也面臨實例類型的問題返回的對象是構造函數(shù)的實例為什么實例函數(shù)不相等呢在中是一種引用類型。使用指定的參數(shù)調(diào)用構造函數(shù),并將綁定到新創(chuàng)建的對象。構造函數(shù)返回的對象就是表達式的結果。 有了前面幾節(jié)的知識,這一節(jié)我們理解起來就要輕松很多。在 javascript 里函數(shù)也是對象,瀏覽器的全局上下文也是對象, key - value 的身影在代碼里比較常見,合理的使用對象多維...
閱讀 3005·2021-11-25 09:43
閱讀 3628·2021-11-24 11:13
閱讀 3401·2021-10-14 09:42
閱讀 2600·2021-09-23 11:53
閱讀 3641·2021-09-22 15:57
閱讀 3260·2021-09-02 09:54
閱讀 3532·2019-08-30 13:47
閱讀 1667·2019-08-29 16:55