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 同時有
prototypeproperty,又有 prototype object,且 function 又有 Object 特性,才導致 prototype 觀念混在一起 - Function 的
prototypeproperty 並不是指向其 prototype Object,__proto__property 才是 - Function 的
prototypeproperty 只有在當其搭配new成為 constructor function 時才有意義,prototypeproperty 所指向的 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