這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 原型和原型鏈 1. 原型 每個JS對象一定對應一個原型對象,並從原型對象繼承屬性和方法 1.1 __proto__ 對象的__proto__屬性值就是對象的原型對象 此屬性是過時的語法,現在建議使用Object.getPrototypeo ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
原型和原型鏈
1. 原型
每個JS對象一定對應一個原型對象,並從原型對象繼承屬性和方法
1.1 __proto__
對象的__proto__
屬性值就是對象的原型對象
此屬性是過時的語法,現在建議使用Object.getPrototypeof(obj)
函數也是對象,因此也有__proto__
屬性
1.2 Prototype
函數的prototype屬性值就是函數的原型對象
定義:給其他對象提供共用屬性的對象,prototype 本身也是對象,只是被用以承擔某個職能
當說 prototype 對象時,實際上說的是 “xxx 函數對象的 prototype 對象”
1.3 constructor
每個原型都有一個 constructor 屬性指向關聯的構造函數
實例訪問 constructor 屬性是獲取的原型對象的構造函數
function Person(age) { this.age = age; } let p = new Person(50); console.log(Person.prototype.constructor === Person); // true console.log(p.constructor === Person); // true 會查找原型對象
對於引用類型來說 constructor
屬性值是可以修改的,但是對於基本類型來說是只讀的,因為創建他們的是只讀的原生構造函數(native constructors
)
2. 原型鏈
每個對象擁有一個原型對象,通過 __proto__
指針指向上一個原型 ,並從中繼承方法和屬性,同時原型對象也可能擁有原型,這樣一層一層,最終指向 null
。這種關係被稱為原型鏈 (prototype chain),通過原型鏈一個對象會擁有定義在其他對象中的屬性和方法。
因此,當讀取實例的屬性時,如果找不到,就會查找與對象關聯的原型中的屬性,如果還查不到,就去找原型的原型,一直找到最頂層為止。
2.1 原型鏈知識點
-
原型鏈的盡頭(root)是
Object.prototype
。所有對象(除null)均從Object.prototype
繼承屬性 -
Object.prototype.__proto__
值是null,原型鏈終止 -
Function.prototype
和Function.__proto__
為同一對象意味著:
Object
/Array
/String
等等構造函數本質上和Function
一樣,均繼承於Function.prototype
-
Function.prototype
直接繼承root(Object.prototype
) -
繼承的原型鏈:
Object.prototype(root)
<---Function.prototype
<---Function|Object|Array...
-
對象的
__proto__
指向自己構造函數的prototype
-
ES規範定義對象字面量({})的原型就是
Object.prototype
2.2 Object
和Function
的雞和蛋的問題
Function.prototype
是個不同於一般函數(對象)的函數(對象)Function.prototype
像普通函數一樣可以調用,但總是返回undefined
。- 普通函數實際上是
Function
的實例,即普通函數繼承於Function.prototype
。func.__proto__ === Function.prototype
。 Function.prototype
繼承於Object.prototype
,並且沒有prototype
這個屬性。func.prototype
是普通對象,Function.prototype.prototype
是null
。- 總結,
Function.prototype
其實是個另類的函數,可以獨立於/先於Function
產生。
- Object本身是個(構造)函數,是Function的實例,即
Object.__proto__
就是Function.prototype
問題總結:
先有Object.prototype(原型鏈頂端),Function.prototype繼承Object.prototype而產生,最後,Function和Object和其它構造函數繼承Function.prototype而產生
2.3 原型鏈圖解
原型和原型鏈經典關係圖
自己畫的原型圖
圖解描述:
Person、Object、Function是函數對象,具備prototype屬性,其他對象是只有__proro__
獲取原型對象
Person.__proto__及Object.__proto__與Function.__proto__相等,是ƒ () { [native code] }
Person.__proto__及Object.__proto__與Function.__proto__的原型對象為Object.prototype
Function.__proto__和Function.prototype值相等,為空函數: ƒ () { [native code] }
Person.constructor、Object.constructor與Function值相等,為: ƒ Function() { [native code] }
原型鏈代碼輸出結果
function Person(name) { this.name = name } var p2 = new Person('king'); console.log(p2.__proto__) //Person.prototype console.log(p2.__proto__.__proto__) //Object.prototype console.log(p2.__proto__.__proto__.__proto__) // null console.log(p2.__proto__.__proto__.__proto__.__proto__) //null後面沒有了,報錯 console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__) //null後面沒有了,報錯 console.log(p2.constructor)//Person console.log(p2.prototype)//undefined p2是實例,沒有prototype屬性 console.log(Person.constructor)//Function 一個空函數 console.log(Person.prototype) //列印出Person.prototype這個對象里所有的方法和屬性 console.log(Person.prototype.constructor)//Person console.log(Person.prototype.__proto__)// Object.prototype console.log(Person.__proto__) //Function.prototype console.log(Function.prototype.__proto__)//Object.prototype console.log(Function.__proto__)//Function.prototype console.log(Object.__proto__)//Function.prototype console.log(Object.prototype.__proto__)//null console.log(Function); // ƒ Function() { [native code] } 空函數,名為Function console.log(Object.constructor); // ƒ Function() { [native code] } console.log(Person.constructor); // ƒ Function() { [native code] } console.log(Function === Object.constructor); // true console.log(Function === Person.constructor); // true console.log(Function.__proto__); // ƒ () { [native code] } console.log(Function.prototype); // ƒ () { [native code] } console.log(Function.__proto__ == Function.prototype); // true console.log(Function.__proto__.__proto__ === Object.prototype) // true console.log(Function.prototype.__proto__ === Object.prototype) // true