iT邦幫忙

2022 iThome 鐵人賽

DAY 15
2

前言

這篇要介紹的是用 Object.create() 這個函式。


語法

Object.create(proto[, propertiesObject])

帶入的兩個參數分別為:

  1. proto,傳入的該物件會變成新物件的 prototype 物件,如果不是 null 或是物件,會拋出錯誤。
  2. propertiesObject,是一個物件,裡面放要加到新增物件的屬性或是可以修改新增物件的屬性值

帶入兩個參數後,會從指定的 prototype 物件建立一個新物件,並加上第二個參數的屬性,那這樣產生新物件可以做什麼?我們繼續看下去吧!


從範例認識 Object.create()

讀者可以先閱讀以下程式碼:

function Shape(x, y) {
  this.x = x;
  this.y = y;
}

Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
};

function Rectangle(...args) {
  Shape.apply(this, args);
}

const properties = {
  name: {
    value: "長方形",
    enumerable: true,
    writable: true,
  },
  getPos: {
    value: function () {
      console.log(`Current Position: ${this.x}, ${this.y}.`);
    },
  },
};

// Rectangle 繼承 Shape 物件
Rectangle.prototype = Object.create(Shape.prototype, properties);
Rectangle.prototype.constructor = Rectangle;

const rect = new Rectangle(0, 0);

閱讀完程式碼後,我們把一些函式的相關資訊都印出來看看:

Rectangle 的原型物件變成了 Shape 物件加上 Object.create() 第二個參數屬性後的物件,其它屬性則和一般函式沒什麼不一樣。

Shape 函式也沒什麼不一樣。

繼續觀察 Rectangle 的原型物件,它的 __proto__ 為 Shape 函式的原型物件,但它的建構子指向 Rectangle。

而 new 關鍵字用來建立實體,像範例中的 react 物件。

我們將上面的內容畫成圖片來看:

可以看到 Object.create() 產生的物件在左下角(有最長黑色說明文字的那個),它的兩個屬性指向可以解釋以下兩行程式碼:

Rectangle.prototype = Object.create(Shape.prototype, properties);
Rectangle.prototype.constructor = Rectangle;

第一行就是透過 Object.create() 產生物件,它的 __proto__ 是指向 Shape.prototype,所以這樣 Rectangle 函式產生的物件,也能透過原型鏈去取到 Shape 的函式。

第二行則是將 Object.create() 產生的物件的建構子,指向繼承的函式,所以可以看到左下角的物件 constructor 指向 Rectangle 函式。

透過這些分析,我們瞭解了 Object.create() 在程式背後實踐繼承的原理,也瞭解了為什麼透過上面兩行程式就可以讓 Rectangle 函式能繼承到 Shape 函式的一些屬性和方法。


其他範例

來看些特別的例子,如果 Object.create() 的第一個參數是傳入 Object.prototype 的話,obj 變數就像是宣告了空物件一樣,也會有物件的一些屬性方法,但如果傳入 null,就不會有物件的任何屬性方法

const obj = Object.create(Object.prototype);
// 等同於: const obj = {};

const empty = Object.create(null);
// empty => null


練習題

文章的最後來個小練習題吧,這題是來自於 臉書的一篇貼文,若前面的內容有了解的話,這篇答案就很輕易知道囉~

const employee = {
  company: 'levelhunt'
};

const empl = Object.create(employee);
delete empl.company;
console.log(empl.company); // ?

練習解答

雖然刪除了 empl 物件本身的屬性,但它的 prototype 實際上不會影響,所以還是會印出 'levelhunt'。


參考資料 & 推薦閱讀

Object.create()

JavaScript 核心觀念(51)- 繼承與原型鍊 - 使用 Object.create 建立多層繼承


上一篇
Day14-ES6 Class 繼承
下一篇
Day16-instanceof 介紹
系列文
強化 JavaScript 之 - 程式語感是可以磨練成就的30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言