理解Object.defineProperty的作用

678 阅读1分钟

前言

我们都知道vue2基于Object.defineProperty实现双向绑定的,达到监听数据变动的目的。

Object.defineProperty() 的定义

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。 Object.defineProperty(obj, prop, descriptor) obj: 要定义的参数 prop: 要定义的或修改的属性名 descriptor: 要定义修改的属性描述符 属性描述符writable

const obj = {}
Object.defineProperty(obj, 'property1',{value:"zz",writable:true});
//writable:是否可以修改
obj.property1 = "hh"
console.log(obj);
// {property1:"hh"}

属性描述符enumerable

var obj = {}
//第一种情况:enumerable设置为false,不能被枚举。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false
});

//枚举对象的属性
for( var attr in obj ){
    console.log( attr );  
}
//第二种情况:enumerable设置为true,可以被枚举。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:true
});

//枚举对象的属性
for( var attr in obj ){
    console.log( attr );  //newKey
}

属性描述符get,set

const obj = {};
Object.defineProperty(obj, 'property1', {
    get: function () {
    
    },
    set: function (val) {
        console.log(val)
    }
})
obj.property1 = "zz"
console.log(obj)
// {property1:"zz"}

获取函数和设置函数不一定都要定义。只定义获取函数意味着属性是只读的,尝试修改属性会被忽 略。在严格模式下,尝试写入只定义了获取函数的属性会抛出错误。类似地,只有一个设置函数的属性 是不能读取的,非严格模式下读取会返回 undefined,严格模式下会抛出错误。

实现即简版的双向绑定

const obj = {};
Object.defineProperty(obj, 'text', {
  get: function() {
    console.log('get val');
  },
  set: function(newVal) {
    console.log('set val:' + newVal);
    document.getElementById('input').value = newVal;
    document.getElementById('span').innerHTML = newVal;
  }
});

const input = document.getElementById('input');
input.addEventListener('keyup', function(e){
  obj.text = e.target.value;
})