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>
