理解Object.defineProperty

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或在修改一个对象的现有属性,并返回这个对象(即第一个参数obj)

语法:

Object.defineProperty(obj , prop , descriptor)


//
obj:要在其上定义属性的对象 //prop:要定义或修改的属性的名称 //descriptor:将被定义或修改的属性描述符

 vue.js就是通过Object.defineProperty实现双向绑定

 

给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述

数据描述

当修改或定义对象的某个属性的时候,给这个属性添加一些特性

value: 设置属性的值
writable: 值是否可以重写。true | false
enumerable: 目标属性是否可以被枚举。true | false
configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false

 

value:属性对应的值,可以是任意类型的值,默认为undefined

let obj = {}
//第一种情况:不设置value属性
Object.defineProperty(obj,"newKey",{

});
console.log( obj.newKey );  //undefined
------------------------------
//第二种情况:设置value属性
Object.defineProperty(obj,"newKey",{
    value:"hello"
});
console.log( obj.newKey );  //hello

 

writable:属性的值是否可以被重写,默认为false,设置为true可以被重写

    let Person = {};
    Object.defineProperty(Person,'city',{
        city:'伦敦'
        //writable默认为false,不能改变属性值
    })
    Person.city = '巴黎';
    console.log(Person.city);//undefined
   let Person = {};
    Object.defineProperty(Person,'city',{
        city:'伦敦',
        writable:true
    })
    Person.city = '巴黎';
    console.log(Person.city);//巴黎

 

enumerable:此属性是否可以被枚举

设置为true可以被枚举;设置为false,不能被枚举(默认false)

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
}

 

configurable:是否可以删除目标属性或是否可以再次修改属性的特性

设置true可以被删除或可以重新设置特性,false不能设置

这个属性起到的作用

  1. 目标属性是否可以使用delete删除

  2. 目标属性是否可以再次设置特性

//-----------------测试目标属性是否能被删除------------------------
var obj = {}
//第一种情况:configurable设置为false,不能被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //hello

//第二种情况:configurable设置为true,可以被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //undefined
//-----------------测试是否可以再次修改特性------------------------
var obj = {}
//第一种情况:configurable设置为false,不能再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});

//重新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey

//第二种情况:configurable设置为true,可以再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});

//重新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //hello

一旦使用Object.defineProperty给对象添加属性,那么如果不设置属性的特性,那么configurable、enumerable、writable这些值都为默认的false

 

存取器描述

当使用存取器描述属性的特性的时候,允许设置以下特性属性

当设置或获取对象的某个属性的值的时候,可以提供getter/setter方法,没有的话则为undefined

  • getter 是一种获得属性值的方法

  • setter是一种设置属性值的方法

注意:当使用了getter或setter方法,不允许使用writable和value这两个属性

var obj = {};
var initValue = 'hello';
Object.defineProperty(obj,"newKey",{
    get:function (){
        //当获取值的时候触发的函数
        return initValue;    
    },
    set:function (value){
        //当设置值的时候触发的函数,设置的新值通过参数value拿到
        initValue = value;
    }
});
//获取值
console.log( obj.newKey );  //hello

//设置值
obj.newKey = 'change value';

console.log( obj.newKey ); //change value

get或set不是必须成对出现,任写其一就可以。如果不设置方法,则get和set的默认值为undefined

      let obj = {
          num:4
      };
       let n = 2;
      Object.defineProperty(obj,'num',{
          get:function(){   //取 obj.num 属性时会触发 get 方法
              /*数据劫持*/
              //当你获取这个属性的时候,会调用
               n += 2;
              return n;
          },
       set(val){   //给 obj.num 赋值时会触发 set 方法
         //val 是给 obj.num 赋值时的那个值 
       }

      });
      console.log(obj.num < 5 && obj.num > 5);//true
  /*num即小于5,又大于,就是应为,第一次判断obj.num时num=(n+=2)=4,符合了第一个条件,此时的n=4。
 读到第二个判断的时候,再次触发函数,此时n+=之后为6,又符合了第二个判断条件,所以出现了true*/        

 

posted @ 2019-03-09 11:37  紫诺花开  阅读(316)  评论(0编辑  收藏  举报