属性描述符
这里就不说怎么去创建对象,取和修改对象的值这些了。从ES5开始,所有的对象都具备了属性描述符,
let person = {
name:"陈志元"
};
Object.defineProperty(person, "name", {
configurable: true,
writable: true,
enumerable: true,
value: "陈志元",
});
如你所见,这个普通的对象属性对应的属性描述符,可不仅仅只是一个"丁时一",它还包含另外三个特性configurable,writable,enumerable
writable
writable决定是否可以修改。
let person = {};
Object.defineProperty(person, "name", {
configurable: true,
writable: true,
enumerable: true,
value: "陈志元",
});
console.log(person.name); //陈志元
person.name = "帅哥";
console.log(person.name); //帅哥
将writable修改为false后
"use strict";
let person = {};
Object.defineProperty(person, "name", {
configurable: true,
writable: false, //不可写!
enumerable: true,
value: "陈志元",
});
console.log(person.name); //陈志元
person.name = "帅哥"; //在模式下 Cannot assign to read only property "name" of object "#<Object>"
console.log(person.name); //陈志元
在非严格模式下,修改会静默失败,但在严格模式下,就会抛出TypeError错误!
configurable
configurable表示属性是否可配置。只要属性是可配置的,就可以使用Object.defineProperty来修改属性描述符。
let myobj={
a:3
}
myobj.a=4
console.log(myobj.a);//4
Object.defineProperty(myobj,"a",{
configurable:false,//不可配置!
writable:true,
value:4
})
myobj.a=5
console.log(myobj.a);//5
Object.defineProperty(myobj, "a", {
configurable: true,
writable: true,
});//TypeError
最后一个Object.defineProperty会产生一个TypeError,不管是否处于严格模式,尝试修改一个不可配置的属性描述符都会发生错误,所以把configurable设置为false是单向操作!
补充
在《JavaScript高级程序设计》(第四版)中有提到:一个属性被定义为不可配置之后,再次调用Object.defineProperty()并修改除writable以外的属性都会导致错误
这里我提一下,在configurable为false的情况下,还是可以把writable从true改为false,但是由false改为true就会导致错误!
由true变false
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
writable: true,
enumerable: true,
value: "陈志元",
});
console.log(person); // {name: "陈志元"}
person.name = "丁青年";
console.log(person); //{name: "丁丁"}
//现在尝试把writeable修改为false
//没有报错
Object.defineProperty(person, "name", {
configurable: false,
writable: false,
value: "啦啦啦",
});
console.log(person); //{name: "啦啦啦""}
由false变true
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
writable: false,
enumerable: true,
value: "陈志元",
});
//现在尝试把writeable改为true
//报错 Cannot redefine property: name at Function.defineProperty (<anonymous>)
Object.defineProperty(person, "name", {
configurable: false,
writable: true,
value: "啦啦啦",
});
并且除了无法修改,configurable:false还会禁用删除这个属性
const obj={
name:"丁时一"
}
delete obj.name
console.log(obj);//{} 属性被删除
Object.defineProperty(obj,"name",{
configurable:false,
value:"丁时一"
})
delete obj.name
console.log(obj);//{name: "丁时一"}
enumerable
控制属性是否会出现在对象的枚举当中,比如说for…in循环,如果enumerable为false那么这个属性就不会出现在枚举当中
let person = {};
Object.defineProperty(person, "name", {
configurable: true,
writable: true,
enumerable: true, //可枚举
value: "陈志元",
});
Object.defineProperty(person, "age", {
configurable: true,
writable: true,
enumerable: false, //不可枚举
value: 20,
});
console.log(person); //{name: "陈志元", age: 20}
for (let i in person) {
//并没有age 因为age不可枚举
console.log(i, person[i]); //name 陈志元
}
结尾
在调用Object.defineProperty()时,如果这三个参数都不指定,那么全部默认为false,我们可以使用 Object.defineProperties给对象同时定义多个属性
const obj = {};
Object.defineProperties(obj, {
name: {
value: "陈志元",
},
age: {
value: 20,
},
});
obj.name="帅哥"
console.log(obj.name);//陈志元 writable默认false
for(let i in obj){
console.log(i);//没有打印 enumerable默认false
}
Object.defineProperty(obj,"name",{
configurable:true
})//TypeError 因为我们正在尝试修改一个不可配置属性
这里我们定义了一个不可枚举属性age,虽然能够正常的访问它,但是并没有出现在枚举当中。
今天就到这里啦~如果有什么不足的地方,希望各位看官评论区提醒哦AwA