Javascript之Object.defineProperty方法

靈境衚衕發表於2019-04-09

ES5的Object中有一個方法:Object.defineProperty,這個方法可以直接在一個物件上定義一個新屬性,或者修改一個物件的現有屬性,並返回這個物件(摘自MDN)。

1.基本語法

Object.defineProperty(obj, prop, descriptor)
複製程式碼

其中:

obj:        (必需, Object) 即將在其上定義屬性的目標物件
prop:       (必需, String) 即將定義(或修改)的屬性的名稱
descriptor: (必需, Object) 即將被定義(或修改)的屬性的描述符
複製程式碼

前兩個引數好理解,主要是第三個引數比較麻煩。在分析第三個引數前,先舉一個例子:

let Product = {};
Object.defineProperty(Product, "discount", {
    // 對discount屬性的描述
})
複製程式碼

在上面的程式碼中,我建立了一個Product物件,併為其新增了一個discount屬性,而第三個引數則是對該屬性的描述.

接下來我們要詳細分析一下descriptor引數,即屬性的描述符。

2.屬性描述符

屬性描述符可以有兩種形式:資料描述符存取描述符,這兩種形式的鍵值有的相同,有的不同,具體如下:

2.1 公共鍵值

configurable
複製程式碼

當且僅當該屬性的configurable為true時,該屬性描述符才能夠被改變,同時該屬性也能從對應的物件上被刪除。預設為false。

enumerable
複製程式碼

當且僅當該屬性的enumerable為true時,該屬性才能夠出現在物件的列舉屬性中。預設為 false。

2.2 資料描述符的可選鍵值

value
複製程式碼

該屬性對應的值。可以是任何有效的JavaScript值(數值,物件,函式等)。預設為undefined。

writable
複製程式碼

當且僅當該屬性的writable為true時,value才能被賦值運算子改變。預設為false。

2.3 存取描述符的可選鍵值

get
複製程式碼

一個給屬性提供 getter 的方法,如果沒有 getter 則為 undefined。當訪問該屬性時,該方法會被執行,方法執行時沒有引數傳入,但是會傳入this物件(由於繼承關係,這裡的this並不一定是定義該屬性的物件)。 預設為 undefined。

set
複製程式碼

一個給屬性提供 setter 的方法,如果沒有 setter 則為 undefined。當屬性值修改時,觸發執行該方法。該方法將接受唯一引數,即該屬性新的引數值。 預設為 undefined。

綜上,現在我可以通過資料描述符為物件新增一個屬性:

let Product = {};
Object.defineProperty(Product, "discount", {
    value: 20,
    writable: true,
    configurable: true,
    enumerable: true
})
複製程式碼

也可以通過存取描述符為物件新增屬性:

let Product = {},
    value = 1;
Object.defineProperty(Product, "discount", {
    get: function () {
        return value;
    },
    set: function (newValue) {
        value = newValue;
    },
    configurable: true,
    enumerable: true
})
複製程式碼

此外,一定要注意:屬性描述符可以是資料或存取描述符的其中一種,但是千萬不能混用。比如這樣:

let Product = {};
Object.defineProperty(Product, "discount", {
    value: 20,
    writable: true,
    // get不能與value,writable同時使用!!
    get: function () {
        return 20;
    },
    configurable: true,
    enumerable: true
})
複製程式碼

這是錯誤的!

3.相容性

IE8以下是不相容的。

Javascript之Object.defineProperty方法

參考資料:

  1. developer.mozilla.org/zh-CN/docs/…
  2. imweb.io/topic/56d40…

相關文章