ES5的Object中有一個方法:Object.defineProperty,這個方法能夠直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,並返回這個對象(摘自MDN)。web
Object.defineProperty(obj, prop, descriptor)
複製代碼
其中:bash
obj: (必需, Object) 即將在其上定義屬性的目標對象
prop: (必需, String) 即將定義(或修改)的屬性的名稱
descriptor: (必需, Object) 即將被定義(或修改)的屬性的描述符
複製代碼
前兩個參數好理解,主要是第三個參數比較麻煩。在分析第三個參數前,先舉一個例子:函數
let Product = {};
Object.defineProperty(Product, "discount", {
// 對discount屬性的描述
})
複製代碼
在上面的代碼中,我建立了一個Product對象,併爲其添加了一個discount屬性,而第三個參數則是對該屬性的描述.ui
接下來咱們要詳細分析一下descriptor參數,即屬性的描述符。this
屬性描述符能夠有兩種形式:數據描述符和存取描述符,這兩種形式的鍵值有的相同,有的不一樣,具體以下:spa
configurable
複製代碼
當且僅當該屬性的configurable爲true時,該屬性描述符纔可以被改變,同時該屬性也能從對應的對象上被刪除。默認爲false。code
enumerable
複製代碼
當且僅當該屬性的enumerable爲true時,該屬性纔可以出如今對象的枚舉屬性中。默認爲 false。cdn
value
複製代碼
該屬性對應的值。能夠是任何有效的JavaScript值(數值,對象,函數等)。默認爲undefined。對象
writable
複製代碼
當且僅當該屬性的writable爲true時,value才能被賦值運算符改變。默認爲false。blog
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
})
複製代碼
這是錯誤的!
IE8如下是不兼容的。
參考資料: