Object.create

  • 另一個建立物件的方法,沒有模仿別的程式語言。
  • 現在的瀏覽器幾乎都有內建。
  • 建立一個物件當作基本物件,然後在這個物件上建立新物件。

使用範例:先建立一個物件 person 作為基本物件,然後用 Object.create 在這個物件上建立新物件 sealman

var person = {
  firstname: 'Default',
  lastname: 'Default',
  greet: function() {
    return 'Hi ' + this.firstname;
  },
};

console.log(person.greet()); // Hi Default

var sealman = Object.create(person); // 從傳入的物件上建立物件
console.log(sealman); // 是一個空物件,它的原型是 person 物件
console.log(sealman.greet()); // Hi Default

注意:如果沒有用 this,執行時會到全域執行環境中找 firstname,因為全域中只有 person,而 person 是物件所以不會建立執行環境,最後結果就會找不到 firstname

使用 Object.create 後,可以再建立新物件的屬性和方法去覆蓋原型給的預設值。
執行時,原型鏈找到新物件就會停止,不會繼續往下找。

sealman.firstname = 'Sealman';
sealman.lastname = 'Huang';
console.log(sealman.greet()); // Hi Sealman
console.log(sealman); // {firstname: "Sealman", lastname: "Huang"}

Polyfill

不過 Object.create 算是比較新的寫法,如果要支援比較舊的瀏覽器,可以加上 Polyfill 的程式碼。

  • Polyfill:把引擎(像是舊瀏覽器的 JavaScript 引擎)缺少的功能增加到程式裡面的程式碼。
  • Polyfill 會先檢查當下使用的引擎有沒有某個功能,如果沒有就會幫忙加上去,讓舊的瀏覽器有新型瀏覽器的功能。

首先,一開始的 if (typeof Object.create !== "function") 就是在檢查瀏覽器有沒有 Object.create 這個東西,如果存在就會直接跳過這整段 if 陳述句。

接下來 temp.__proto__ = proto 就是在設定物件 temp 的原型等於我們傳入的物件 proto
這就相當於 var temp = Object.create(proto) 的意思,也就是用 proto 作為原型來建立新物件 temp,最後回傳 temp 完成物件建立。

if (typeof Object.create !== 'function') {
  Object.create = function(proto, propertiesObject) {
    if (
      !(
        proto === null ||
        typeof proto === 'object' ||
        typeof proto === 'function'
      )
    ) {
      throw TypeError('Argument must be an object, or null');
    }
    var temp = new Object();
    temp.__proto__ = proto;
    if (typeof propertiesObject === 'object')
      Object.defineProperties(temp, propertiesObject);
    return temp;
  };
}

所以上面這一整段 Polyfill 的意思就是「給一個物件 proto,它會變成新的空物件 temp 的原型」,其實就跟 var temp = Object.create(proto) 的效果是一樣的。

回顧

看完這篇文章,我們到底有什麼收穫呢?藉由本文可以理解到…

  • 更純粹、強大、易懂的原型繼承 - Object.create。
  • 使用 Polyfill 補足舊瀏覽器缺少的功能。

References