defineProperty的使用
1.defineProperty的使用
// eg one const object1 = {}; Object.defineProperty(object1, 'property1', { value: 42, // writable:false //默认 // configurable:false; //默认 // enumerable:false //默认 }); object1.property1 = 24; console.log(object1.property1);//42 // eg two const object1 = {property1:42}; //property默认可读可写可配置可枚举 Object.defineProperty(object1,'property1',{ value: 24 }); object1.property1 = 18; console.log(object1.property1); //18 //不是说好的,Object.defineProperty中定义的属性是默认是不可写,不可配置,不可枚举的? const property = Object.getOwnPropertyDescriptor(object1, "property1") console.log(property);//{value: 18, writable: true, enumerable: true, configurable: true} //结论 // Object.defineProperty(obj, prop, descriptor) // 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。 // 定义新属性的时候: 默认设置(描述符) 是不可写,不可配置,不可枚举 // 修改现有属性: 会保留之前属性的描述符 只修改对应的描述符 // 下面是MDN的一个例子 var o = {}; o.a = 1; // 等同于: Object.defineProperty(o, "a", { value: 1, writable: true, configurable: true, enumerable: true }); // 另一方面, Object.defineProperty(o, "a", { value : 1 }); // 等同于: Object.defineProperty(o, "a", { value: 1, writable: false, configurable: false, enumerable: false }); //but 利用defineProperty()来修改属性描述符时, //必须保证属性是可配置的,也就是configurable:true //下面又是一个例子 var myObj = {a:2}; myObj.a = 3; myObj.a;//3 Object.defineProperty(myObj,"a",{ value:4, writable:true, configurable:false,//不可配置 enumerable:true }); myObj.a; //4 myObj.a = 5; myObj.a;//5 Object.defineProperty(myObj,"a",{ value:4, writable:true, configurable:true, enumerable:true });//TypeError //最后一个 defineProperty(..) 会产生一个 TypeError 错误, //不管是不是处于严格模式,尝 试修改一个不可配置的属性描述符都会出错。 //注意:如你所见,把 configurable 修改成 false 是单向操作,无法撤销! //同样的道理,enumerable也只能是单向的,修改会报错 Object.defineProperty(myObj,"a",{ value:4, writable:true, configurable:false,//只能单向改变 enumerable:false,//只能单向改变 });//TypeError:Cannot redefine property: a // 要注意有一个小小的例外:即便属性是 configurable:false, // 我们还是可以 把 writable 的状态由 true 改为 false, // 但是无法由 false 改为 true。 Object.defineProperty(myObj,"a",{ value:4, writable:false,// true可以改成false configurable:false,//保持不变 enumerable:true,//保持不变 }); myObj.a = 333; myObj.a;// 5
2.defineProperty双向绑定的实现
<div></div> <input type="text"> <script> let obj = {}; function watch(obj,name,callback){ let value = obj.name; Object.defineProperty(obj,name,{ set(msg){ value = msg; callback(value); }, get(){ return value; } }); }; function doSomething(value){ document.querySelector('div').innerHTML = value; document.querySelector('input').value = value; } document.querySelector('input').addEventListener('input',(e) => { obj['msg'] = e.target.value; }); watch(obj,'msg',doSomething); </script>