Object 有 3 個非常像的 Property:__proto__
、prototype
與 [[prototype]]
,徹底了解有助於我們看清 Prototype 本質。
Version
ECMAScript 2015
Class
class Book {
constructor(title, price) {
this.title = title
this.price = price
}
showDescription() {
return `${this.title} / ${this.price}`
}
}
let book = new Book('FP in JavaScript', 100)
book.showDescription() // ?
這是 ES6 的 class,包含 title
、price
property 與 showDescription()
method。
Constructor Function
let Book = function(title, price) {
this.title = title
this.price = price
}
Book.prototype.showDescription = function() {
return `${this.title} / ${this.price}`
}
let book = new Book('FP in JavaScript', 100)
book.showDescription() // ?
Class 其實是 constructor function 的 syntatic sugar,showDescription()
會定義在 Book.prototype
。
目前為止 book.__proto__
指向 Book.prototype
,因此我們能透過 Book.prototype
去新增 method,等效於對 book.__proto__
新增 method。
prototype
Q:我明明只定義
Book()
,為什麼橫空出世有了Book.prototype
呢 ?
當 function 建立時,無論是 constructor function 或一般 function,由於 function 也是 Object,因此自帶 prototype
property 指向 Object,而該 Object 的 prototype 正是來自於 Object.prototype
。
_proto_
Q:為什麼有了
prototype
,又有了__proto__
?
先澄清一個觀念,prototype
為 function 專屬 property;而 __proto__
為 Object 專屬 property,但因為 function 也是 Object,所以 function 同時有 prototype
與 __proto__
。
__proto__
指向 Object 的 prototype,如 book
與 Book.prototype
都是 Object,因此其 __proto__
都不約而同的指向 Object.prototype
。
那 Book()
的 prototype 呢?可發現 Book()
的 prototype 是 Function.prototype
,而 Function.prototype
的 prototype 是 Object.prototype
。
[[prototype]]
至於 [[prototype]]
呢 ? 根據 ECMAScript 規格,[[prototype]]
屬於 internal property,過去外界只能透過 Object.getPrototypeOf()
與 Object.setPrototypeOf()
去取得 [[prototype]]
property,但 ES6 定義了 __proto__
之後,外界可直接透過 __proto__
存取 [[prototype]]
,也就是目前 __proto__
與 [[prototype]]
意義相同,都是指向 Object 的 prototype。
Conclusion
- 其實 prototype 觀念並不難,只是 ECMAScript 同時有
prototype
property,又有 prototype object,且 function 又有 Object 特性,才導致 prototype 觀念混在一起 - Function 的
prototype
property 並不是指向其 prototype Object,__proto__
property 才是 - Function 的
prototype
property 只有在當其搭配new
成為 constructor function 時才有意義,prototype
property 所指向的 Object 會成為新 Object 的 prototype Object
Reference
許國政, 008 天重新認識 JavaScript
Peter Chang, JavaScript 必須知道的繼承 prototype
Dmitry Soshnikov, JavaScript. The Core.
Kenneth Kin Lum, JavaScript’s Pseudo Classical Inheritance Diagram
Dr.Axel Rauschmayer, Objects and Inheritance