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]] 有三種方式:

  1. __proto__ 屬性或 Object.setPrototypeOf()
  2. ES5 新增的 Object.create()
  3. 建構函式的 prototype 屬性

直接設定物件的 [[Prototype]] 值是緩慢的動作、效能低,而且程式碼難以維護,應該盡量避免這樣的操作。

如果函式的 prototype 屬性,不是預設的物件有重新指派,那裏面將不會有 constructor 屬性,必須手動設置。

TOP