4 年前 Web

Object.defineproperty 实现数据与视图绑定

Object.defineproperty(obj, prop, descriptor) 可以添加/修改对象的属性,调用后会返回该对象。和平时直接添加对象属性:var obj = {title: ''} 是有区别的。通过 Object.defineproperty 定义可以配置对象属性是否可以枚举/删除/可写以及为属性添加自定义的 getter/setter 等特性。

使用

属性不可写

var obj = {}
Object.defineProperty(obj, 'a', {
  // 属性描述符是否可改变和属性是否可删除,默认 false,防止通过 defineProperty 重新定义属性的值,所以要设置为 false
  configurable: false,
  // 是否可写,默认 false
  writable: false,
  // 值
  value: 0
})
// 修改无效,因为属性描述为不可写
obj.a = 10
// 修改无效,因为属性 a 的 configurable 为 false 
Object.defineProperty(obj, 'a', { value: 10 })
consolg.log(obj.a) // 还是 0

属性不可删除

var obj = {}
Object.defineProperty(obj, 'a', {
  configurable: false,
  value: 0
})
// 删除无效,因为属性 a 的 configurable 为 false 
delete obj.a // false
consolg.log(obj.a) // 还是 0

属性不可枚举

var obj = {}
Object.defineProperty(obj, 'a', {
  // 是否可枚举,默认 false
  enumerable: false,
  // 值
  value: 0
})
Object.keys(obj) // []
for (prop in obj) {} // 没有属性

自定义getter/setter

var obj = {}
var value = 10
// 数据描述符和属性描述符 writable 不能同时存在,否则报错
Object.defineProperty(obj, "a", {
  get: function(){
    return value
  },
  set: function(newValue){
    value = newValue
  }
})
obj.a = 20

实现数据与视图绑定

实现一个修改对象属性自动更新页面 UI 的小效果

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

<script>
var input = {}
Object.defineProperty(input, 'value', {
  // 当修改 value 时,执行 render 函数重新渲染
  set: function(newValue){
    render(newValue)
  }
})
function change(value) {
  input.value = value
}
function render(value){
  document.getElementById('J_textInput').value = value
  document.getElementById('J_text').innerText = value
}
input.value = 'test'
</script>