詳解Object.defineProperty()

前言

Object.defineProperty是ES5新增的一個API,其做用是給對象的屬性增長更多的控制。在咱們平常的coding中,這個API用到的地方很少,然而它對於MVVM框架中雙向數據綁定(two-ways data binding)來講是相當重要的一個API,目前vueavalon中的雙向數據數據綁定均是經過它來實現的。vue

使用

Object.defineProperty方法提供了一種直接的方式來定義對象屬性或者修改已有對象屬性。git

語法

Object.defineProperty(obj, prop, descriptor)

參數

obj: 須要定義屬性的對象(目標對象)github

prop: 需被定義或修改的屬性名(對象上的屬性或者方法)app

descriptor: 需被定義或修改的屬性的描述符框架

descriptor

objprop都比較好理解,咱們重點來解析第三個參數屬性描述符,它是一個對象,裏面有如下取值:函數

value: 屬性的值spa

var a = {}

Object.defineProperty(a, 'b', {
    value: 2
})

console.log(a.b); // => 2

writable: 屬性是否能被重寫(rewrite),默認爲falsecode

var a = {}

Object.defineProperty(a, 'b', {
    value: 2,
    writable: false
})

console.log(a.b); // output 2

a.b = 3

console.log(a.b); // still ouput  2

enumerable: 屬性是否能在for ... in或者Object.keys中被枚舉出,來默認爲false對象

var a = {}

Object.defineProperty(a, 'b', {
    value: 2,
    enumerable: false
})

console.log(Object.keys(a)) // output []

Object.defineProperty(a, 'c', {
    value: 2,
    enumerable: true
})

console.log(Object.keys(a)) // output ['c']

configurable: 是否可以配置valuewritableconfigurable,默認爲falseblog

var a = {}

Object.defineProperty(a, 'b', {
    value: 2,
    enumerable: false
})

console.log(a.b) // output 2

Object.defineProperty(a, 'b', {
    value: 3,
    enumerable: true
})

// TypeError: Cannot redefine property: b

get: 一個給屬性提供 getter 的方法,默認undefined

set: 一個給屬性提供 setter 的方法,默認undefined

屬性描述符分爲數據描述符和存取描述符。數據描述符是一個擁有可寫或不可寫值的屬性。存取描述符是由一對 getter-setter 函數功能來描述的屬性。

數據描述符和存取描述符均具備可選鍵值:configurable, enumerable

數據描述符同時具備可選鍵值:value,writable,get,set

用思惟導圖來表示就是:

desc

get/set

對於setget,個人理解是它們是一對勾子(hook)函數,當你對一個對象的某個屬性賦值時,則會自動調用相應的set函數;而當獲取屬性時,則調用get函數。這也是實現雙向數據綁定的關鍵。

var a = {}
var b

Object.defineProperty(a, 'b', {
    get: function() {
        console.log('get b')

        // 咱們能夠在這裏對返回的值作任何操做
        return b + 1
    },
    set: function(newValue) {
        console.log('set b to', newValue)
        b = newValue
    }
})

a.b = 100

console.log(a.b);

/*
output:
  set b to 100
  get b
  101
*/

注意

數據描述符和存取描述符不能混合使用

Object.defineProperty(o, "conflict", {
  // value是數據描述符
  value: 1,
  // get是存取描述符
  get: function() {
    return 2;
  }
});
// throws a TypeError: value appears only in data descriptors, get appears only in accessor descriptors
相關文章
相關標籤/搜索