Object & Prototype
Object (物件) & Prototype (原型)
JavaScript 使用起來會讓你有「所有的東西都是物件」的錯覺
例如,以宣告式(declarative,或稱字面值(literal))宣告的 string 其實是 primitive literal
function 是物件。array[ ] 則是很像其他語言中的陣列的特殊物件
每個物件都聯繫到一個 [[prototype]] 物件,可由此繼承特性。所有從物件實字建立(就是用 { })的物件,都聯繫到 Object.prototype(JavaScript 的標準物件)
例如,函式物件會聯繫到 Function.prototype,而 Function.prototype 會聯繫到 Object.prototype
而函式物件也會同時建立一個 prototype 特性
該特性的值,是一個具有 constructor 特性的物件
且,這個 constructor 特性的值,是一個函式
所以到底在說啥?
在其他使用物件導向(object oriented)設計模式的語言中,類別可以繼成其他類別,類別建立的實例為物件。但 JavaScript 作為一種設計錯誤、疊床架屋的原型語言(prototypal language),它的物件直接繼承其他物件
而且實際上 JavaScript 也不是直接讓物件繼承物件,而是用了一個沒必要的建構式(constructor)去產生物件
ES6 的 class:只講結論-不要用!它只會讓原本就難懂的概念變得更糟糕,並產生新的陷阱,不可能在舊有的程式上引入它使用。雖然 MDN 上說它是語法糖(syntactical sugar),沒有要引入新的 OO 設計模式,但實際上它就是 JavaScript 的 new bad part。
[[prototype]] chain
指的就是,一般正常的情形下,每個物件在被建立時,它們的 [[prototype]] 都會被賦予對另一個物件的參考。而正常的 [[prototype chain]] 的頂端,也就是終點,都會是 Object.prototype
傳統的繼承一詞,暗示其中會有拷貝(copy)的行為;但 JavaScript 不會拷貝物件特性,它只會在物件間建立連結,讓一個物件可以將函式與特性,委派(delegate)給另一個物件
在傳統的類別程式設計模式,我們常會讓父類別與子類別的 outputTask 取同名,以獲得多型的好處。但在委派連結(delegation links)裡,我們要避免取同名,因為遮蔽(shadowing)的規則有矛盾,而且也會讓程式碼難以維護(例如不小心就產生隱含的遮蔽)
補充閱讀資訊(依序閱讀)
.__proto__(唸作 dunder proto (double underscore 的縮唸 )),的參考是 [[prototype]],請將 .__proto__ 想成一個針對 [[prototype]] 的 getter/setter,而不是一個特性而已
再依序看 http://javascript.info/function-prototype 與 http://javascript.info/native-prototypes,但其中的程式碼都是幫助理解用的而已,切勿輕易於實作中使用。然後該網站接下來其他的章節是在講設計模式,用到的時候再看看就好
讓你一口氣了解 constructor、prototype、__proto__(文章為簡中用語,要先習慣一下)
.constructor 指向建立該東西的 Function。 每個 Function 都有 .prototype 特性。 每個 Object 都有 .__proto__ 特性。
Last updated