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