JavaScript 的 原型
JavaScript 物件原型。
同步發表於 HackMD:原型
詳細筆記在 HackMD,這裡就貼總結就好了。
總結

1. [[Prototype]]
JavaScript 中的每個物件具有個特殊的隱藏屬性,在規範中以 [[Prototype]] 命名表示。
[[Prototype]] 的值會是另一個物件的參考或是 null。
這個物件的參考,會稱為「原型」或是「原型物件」。
原型物件也有自己的原型物件,原型物件的原型物件也有自己的原型物件,而這一長串鏈會稱為「原型鏈」。
當物件進行屬性存取的動作時,會先檢視該物件是否有屬性可以呼叫,如果沒有,會順著該物件的 [[Prototype]] 連結往上層尋找。
原型鏈的最頂層為 Object.prototype,它的 [[Prototype]] 值會是 null。
2. __proto__ 屬性
在 ES5 之前,沒有標準的方法可以訪問這個 [[Prototype]]。只能透過瀏覽器為物件提供的 __proto__ 屬性來訪問。
直到 ES5,才有了 Object.getPrototypeOf() 可以查看 [[Prototype]]。到了 ES6 才有 Object.setPrototypeOf() 可以設定它。
而__proto__ 屬性,直到 ES6 為了確保瀏覽器相容才被標準化,
3. [[Prototype]] 預設值
物件、陣列、函式 [[Prototype]] 預設值:
let obj = {};
console.log(obj.__proto__); // Object.prototype
console.log(obj.__proto__.__proto__); // null
let arr = [];
console.log(arr.__proto__); // Array.prototype
console.log(arr.__proto__.__proto__); // Object.prototype
function fun() {}
console.log(fun.__proto__); // Function.prototype
console.log(fun.__proto__.__proto__); // Object.prototype
最終都會指向 Object.prototype
3. Object.create()
ES5 新增的 Object.create(),能建立出一個物件,該物件的 [[Prototype]] 會是輸入的第一個參數。
4. prototype 屬性
每個函式都有 prototype 屬性,它會指向一個物件,該物件有 constructor 屬性會指向原函式。
當函式以建構式呼叫,建立出來的實體物件的 [[Prototype]] 會指向建構函式的 prototype 屬性指向的物件。
5. [[Prototype]] 的指向
設定物件的 [[Prototype]] 有三種方式:
__proto__屬性或Object.setPrototypeOf()- ES5 新增的
Object.create() - 建構函式的
prototype屬性
直接設定物件的 [[Prototype]] 值是緩慢的動作、效能低,而且程式碼難以維護,應該盡量避免這樣的操作。
如果函式的 prototype 屬性,不是預設的物件有重新指派,那裏面將不會有 constructor 屬性,必須手動設置。