defineProperty的如何实现数据代理?

239 阅读1分钟

定义:Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

1: 直接添加

let person = {
    name:'张三',
    sex:'男',
}
Object.defineProperty(person,'age',{
    value:18,
    enumerable:true,//控制属性是否可以枚举,默认值是false,当该属性的值为 true 时,该属性才会出现在对象的枚举属性中。
    writable:true,//控制属性是否可以被修改,默认值是false,当该属性的值为 true 时,才能被赋值运算符改变。
    configurable:true,//控制属性是否可以被删除,默认值是false,当该属性的值为 true 时,该属性能从对应的对象上被删除。  
             
})
console.log(person);

自己写的例子getter和setter

<!-- 容器-->
    <!-- <div id="root">
       <h1>老子要成为全栈</h1>
    </div> -->
    <div id = "root">
      <h2>学校名称:{{name}}</h2>
      <h2>学校地址:{{address}}</h2>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false
      const vm =  new Vue({
      el:"#root",
      data:{
         name:"哈弗",
         address:"漂亮国"
        }
     })
     Object.defineProperty(data,'name',{
            //value:18,
            enumerable:true,//控制属性是否可以枚举,默认值是false,当该属性的值为 true 时,该属性才会出现在对象的枚举属性中。
            writable:true,//控制属性是否可以被修改,默认值是false,当该属性的值为 true 时,才能被赋值运算符改变。
            //configurable:true,//控制属性是否可以被删除,默认值是false,当该属性的值为 true 时,该属性能从对应的对象上被删除。  
            get(){
                console.log("读取name属性");
                return name;
            },
            set(value){
                console.log("修改name的值");
                name = value;
            }              
        })
   </script>

getter和setter原理图:

需要Object.defineProperty()注意点:

1:用Object.defineProperty方法创建一个新属性时,如果不指定configurabel,enumberable,writable特性的默认值都是false,修改已定义的属性特性无限制。 2:Configurable性定义为不可配置就不能把它变回可配置,此时调用Object.defineProperty修改除writable之外的特性都会报错。 3:模拟访问和设置的行为:想要访问器属性模拟默认行为的话,必须的在里面新添一个属性不然会造成循环引用。

4: Object.defineProperty新添加的属性,遍历person时候不会遍历age !!!!

var obj={
a:1
};
 
Object.defineProperty(obj,"a",{
get:function(){
return this.a;
},
 
set:function(val){
this.a=val
}
});
obj.a;// Maximum call stack size exceeded