prototype chain
為什麼會說再呢?
之前有照著老師的文章也寫了兩篇,但是內容跟老師的有 87% 一樣,只是練習一下寫文章的感覺而已。
這次再稍微深入一點點(真的只有一點點),做了些筆記。
prototype
- 只有 function 才有
prototype
屬性 - 當創建一個 function,JavaScript 會自動幫這個 function 添加
prototype
屬性,值是一個有 constructor 的物件(註一) - 當這個 function 被當作建構函數(constructor)調用(就是用 new 來調用),JavaScript 會創建該 constructor 的實例(instance)
- 這個 instance 會繼承 constructor 的
prototype
裡所有屬性跟方法(透過 instance 的__proto__
指向 constructor 的prototype
) A instanceof B
就是從 A 的__proto__.proto__...
去找 B 的prototype
- 所以原型鏈其實是一連串的
__proto__
註一:function 的 prototype
的 constructor 就是 function 自己本身。
__proto__
JavaScript 每個東西(?)都有 __proto__
來標示自己繼承的原型。
const obj = {}
const num = 123
const str = '666'
console.log(obj.__proto__ === Object.prototype) // true
console.log(num.__proto__ === Number.prototype) // true
console.log(str.__proto__ === String.prototype) // true
new
其實當我們 new 了一個新的 instance 時,會發生以下幾件事:
- 建立一個空白的 JavaScript 物件
- 新增
__proto__
屬性到該新物件,這個屬性會指向建構函式的prototype
物件 - 把 this 綁定到該新物件,也就是建構函式中的 this 會指向該新物件
- 如果函式沒有 return 任何東西,就會 return this
名詞釐清
- prototype:本質應該就是個一般物件而已(?)
- Object
- 一般物件:Object literal,就是我們一般在 code 會用
{}
包起來然後在裡面放東西的那個物件,他的原型是Object.prototype
- 構造函數 Object:原型為
Function.prototype
,剛好有個東西叫做Object.prototype
,但其實Object.prototype
比這個構造函數 Object 還要早出現
- 一般物件:Object literal,就是我們一般在 code 會用
- Function
- 一般函式:構造函數 Function 的實例,所以原型是
Function.prototype
- 構造函數 Function:原型為
Function.prototype
- 一般函式:構造函數 Function 的實例,所以原型是
Function.prototype
:所有構造函數的原型,也就是所有構造函數的__proto__
皆指向Function.prototype
Object.prototype
:原型鏈的頂端,prototype 的王者Object.prototype
跟Function.prototype
是獨立於Object
跟Function
特別的存在,要把他們抽出來看
再來看一張圖,可以幫助釐清這些東西
圖片來源:理解JavaScript的原型链和继承 (oyanglul.us)
從這張圖來看就簡單多了,可以分成兩大類:
__proto__
指向Function.prototype
的(建構)函式們__proto__
指向Object.prototype
的物件們
Function 跟 Object 互為 instance
console.log(Function instanceof Object) // true
console.log(Object instanceof Function) // true
如果你知道 instanceof
的機制,而且了解了上面那些關係,那這個雞生蛋蛋生雞的問題就很簡單了。
A instanceof B
就是到 A 的 __proto__...
找 B.prototype
而已
- Function instanceof Object
Function.__proto__ === Function.prototype
Function.prototype.__proto__ === Object.prototype
- 所以
Function.__proto__.__proto__ === Object.prototype
- Object instanceof Function
Object.__proto__ === Function.prototype
從分類來看
prototype
只有尊爵不凡的函式才有
- Object.prototype
- prototype 的王者,所有 prototype 的
__proto__
都會指向Object.prototype
- prototype 的王者,所有 prototype 的
- Function.prototype
- 所有(建構)函式的
__proto__
都會指向Function.prototype
- 所有(建構)函式的
- 其他(建構)函式的 prototype
- 單純的 JavaScript 物件(?),以
Function.prototype
為原型
- 單純的 JavaScript 物件(?),以
建構函式
- JavaScript 原有的建構函式
Function
、Object
、Array
、String
…等。
- 自定義的建構函式
- 自己寫一個 function 當作 constructor,你懂的。
總結
Object.prototype
-> Function.prototype
-> Function
、Object
、String
等其他建構函式