Object & Prototype

Object (物件) & Prototype (原型)

  • JavaScript 使用起來會讓你有「所有的東西都是物件」的錯覺

    • 例如,以宣告式(declarative,或稱字面值(literal))宣告的 string 其實是 primitive literal

    • var strPrimitive = "I am a string";
      
      // 但是引擎會在你使用 strPrimitive.length 或是 strPrimitive.chatAt 時,
      // 自動幫你將它強制轉型(coerces)成 string 物件,
      // 所以你用起來當然就是物件啊~

      function 是物件。array[ ] 則是很像其他語言中的陣列的特殊物件

  • 每個物件都聯繫到一個 [[prototype]] 物件,可由此繼承特性。所有從物件實字建立(就是用 { })的物件,都聯繫到 Object.prototype(JavaScript 的標準物件)

    • 例如,函式物件會聯繫到 Function.prototype,而 Function.prototype 會聯繫到 Object.prototype

  • 而函式物件也會同時建立一個 prototype 特性

    • 該特性的值,是一個具有 constructor 特性的物件

  • 且,這個 constructor 特性的值,是一個函式

  • 所以到底在說啥?

  • // JavaScript:良好部分
    // 建立物件時,用來產生函式物件的「Function 建構式」會執行下面概念的程式碼
    
    this.prototype = {constructor: this};
    
    // 等號左邊的新的函式物件,被給予了一個 prototype 特性
    // 這個特性的值,就是等號右邊是一個包含 constructor 特性的物件
    // 而這個 constructor 特性的值,及等號右邊的 this,則是一個新的函式物件

    在其他使用物件導向(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)的規則有矛盾,而且也會讓程式碼難以維護(例如不小心就產生隱含的遮蔽)

    • 補充閱讀資訊(依序閱讀)

Last updated