Object.defineProperty


为对象设置一个新的属性或修改一个已经存在的属性。这个方法会返回该对象。

MDN:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

兼容性:>IE8 FF Chrome


 参数:Object.defineProperty(obj, prop, descriptor) 

 // @{param} obj  待修改的对象
 // @{param} prop 待修改的属性名称
 // @{param} descriptor 待修改属性的相关描述

 // descriptor要求传入一个对象,其默认值如下:

 {
     configurable: false,
     enumerable: false,
     writable: false,
     value: null,
     set: undefined,
     get: undefined
 }

 // configurable ,属性是否可配置。可配置的含义包括:是否可以删除属性( delete ),是否可以修改属性的 writable 、 enumerable 、 configurable 属性。
 // enumerable ,属性是否可枚举。可枚举的含义包括:是否可以通过 for...in 遍历到,是否可以通过 Object.keys() 方法获取属性名称。
 // writable ,属性是否可重写。可重写的含义包括:是否可以对属性进行重新赋值。
 // value ,属性的默认值。
 // set ,属性的重写器(暂且这么叫)。一旦属性被重新赋值,此方法被自动调用。
 // get ,属性的读取器(暂且这么叫)。一旦属性被访问读取,此方法被自动调用。  

例子

  1. enumerable设置属性是否可以枚举, 默认不能枚举

    
    var obj = {}
    Object.defineProperty(obj, 'a', {
     value: 1,
     enumerable: false
    })
    for(var i in obj){
     console.log(i) // undefined
    }  
    
    
  2. writable设置属性是否可写

    
     var obj = {}
     Object.defineProperty(obj, 'a', {
       value: 1,
       writable: false
     })
     Object.defineProperty(obj, 'b', {
       value: 2,
       writable: true
     })
     obj.a = 10 // 重新赋值
     obj.b = 20 // 重新赋值
     console.log(obj.a) // 1 因为writable为false, 不可写
     console.log(obj.b) // 20 因为writable为true, 可写
    
    
  3. getset 对象的属性被访问或者重新赋值会触发

    
    var obj = {
     a: 1
    }
    Object.defineProperty(obj, 'a', {
     get: function(){
         console.log('get')
     },
     set: function(newValue){
         console.log('set newValue: ', newValue)
     }
    })
    obj.a = 10
    console.log(obj.a)
    // 'set newValue:  10'
    // 'get'
    
    

需要注意的地方:

Object.defineProperty() 方法设置属性时,属性不能同时声明访问器属性( set 、 get )和 writable 或者 value 属性。 意思就是,某个属性设置了 writable 或者 value 属性,那么这个属性就不能声明 get 和 set 了,反之亦然。

利用Object.defineProperty实现简单的数据与视图绑定的效果:


// html
<input id="J_textInput"  type="text" onkeyup="change(this.value)" />
<p id="J_text"></p>  


// javascript
var obj = { }
Object.defineProperty(obj, 'value', {
  set: function(newValue){
    render(newValue)
  }
})
function change(value) {
  obj.value = value
}
function render(value){
  document.getElementById('J_textInput').value = value
  document.getElementById('J_text').value = value
}
obj.value = 'test'