【Object系列】详解Object.defineProperty与Object.defineProperties()

Object.defineProperty(obj, prop, descriptor)

一、定义

该属性能够定义一个对象的新属性,或者修改一个对象已有的属性值,返回这个被处理过的对象
参数:
obj:要操作的对象
prop:obj上要定义或修改的属性
descriptor:属性描述器,用于定义或修改该属性的特性。该属性描述器分为两类:数据描述符和存取描述符。
数据描述符:一个具有值的属性,该值可能是可写的,也可能不是可写的。
存取描述符:由getter-setter函数对描述的属性。
描述符必须是这两种形式之一;不能同时是两者。

二、属性描述器descriptor

1、分类

属性描述器descriptor的key共有6种,分别为:
【Object系列】详解Object.defineProperty与Object.defineProperties()_第1张图片
特别注意以下三点
0.记住,这些选项不一定是自身属性,如果是继承来的也要考虑。为了确认保留这些默认值,你可能要在这之前冻结 Object.prototype,明确指定所有的选项,或者通过 Object.create(null)将proto属性指向null。
1.configurable、enumerable既是数据描述符,又是存取描述符
2.value、writable与get、set只能存在其一,同时存在报错。
3.如果对象可枚举,则使用for…in或Object.keys()可以遍历

2、详解

a.仅为数据描述符——value、writable

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

let obj = Object.create(null);
Object.defineProperty(obj, 'name', {
    value:'zhuangzhuang'
})
console.log(obj);//{"name":"zhuangzhuang"}

writable:属性的值是否能够被重新赋值,true为可以重新赋值,false为不可以重新赋值,默认为false
注意:writable为false,但是实际去重新赋值了,不报错,值也不改变

let obj = Object.create(null);
Object.defineProperty(obj, 'name', {
    value:'zhuangzhuang',
    writable:true
})
obj.name = 'yuhua';
console.log(obj);//{"name":"yuhua"}
Object.defineProperty(obj, 'name', {
    writable:false
})
obj.name = 'zhuangzhuang';
console.log(obj);//{"name":"yuhua"}
b.仅为存储描述器——set/get

当设置或获取对象的某个属性的值的时候,可以提供getter/setter方法。

  • getter 是一种获得属性值的方法。当我们去读取属性的值时,调用getter方法。

  • setter是一种设置属性值的方法。当我们去设定或修改属性值时,调用setter。

let obj = Object.create(null);
let initVal = 'zhuangzhuang';
Object.defineProperty(obj, 'name', {
    get:function(){
        return initVal;
    },
    set:function(setVal){//参数为设置的值
        initVal = setVal;
    }
})
console.log(obj.name);//'zhuangzhuang'
obj.name = 'yuhua';
console.log(obj.name);//'yuhua'

赋值一个初始值’zhuangzhuang’给initVal,当走第一个console.log时,会执行get函数,也就是返回initVal,为’zhuangzhuang’;当走obj.name=’yuhua’时,会执行set函数,将赋的值’yuhua’通过set函数参数传入,给initVal,这时候initVal变成了’yuhua’;然后走第二个console.log时,会走get函数,读取最新的initVal为’yuhua’。

c.既为数据描述符,又为存储描述符

enumerable:此属性是否可以被枚举(使用for…in或Object.keys())。设置为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是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false。


这里分为两点——是否可以删除目标属性、是否可以在此修改属性的特性(writable, configurable, enumerable)


第一点:是否可以删除目标属性

let obj = Object.create(null);
Object.defineProperty(obj, 'name', {
    value:'zhuangzhuang',
    configurable:true
})
console.log(obj.name);//'zhuangzhuang'
delete obj.name;
console.log(obj.name);//undefined

可见,当configurable为true的时,是可以删除该属性的。

let obj = Object.create(null);
Object.defineProperty(obj, 'name', {
    value:'zhuangzhuang',
    configurable:false
})
console.log(obj.name);//'zhuangzhuang'
delete obj.name;
console.log(obj.name);//'zhuangzhuang'

可见,当configurable为false的时,不会删除该属性,并且不报错。


第二点:是否可以再次修改属性的特性(writable, configurable, enumerable)

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.defineProperties()

该方法与Object.defineProperty相似,只不过该方法可以一次性操作多个属性

var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
});

你可能感兴趣的:(前端,趣文,ES6)