什么是属性描述符
1 数据描述符
2 存取描述符
3 获取属性描述符
4 设置属性描述符
4.1 配置writable
4.2 配置configurable
4.3 configurable的特殊性
4.4 配置enumerable
5.同时设置多个属性的属性描述符
6.get和set的用法具体看访问器属性getter和setter帖子。
什么是属性描述符
无论使用字面量创建对象,还是通过new Object创建对象,或者通过类去创建对象都无法对对象的属性进行一些限制,比如是否可以被枚举,是否可以被delete删除,如果我们想对一个属性进行比较精准的控制,就需要使用到属性描述符。属性描述符需要使用Object.defineProperty来对象属性进行添加或者修改。
属性描述符分为两种:数据描述符(数据属性)和存取描述符(访问器属性)。
1 数据描述符
数据描述符一般是指数据属性的描述符,具有以下可选键值:
- value:该属性对应的值。
- writable:当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为false。
- configurable:当且仅当该属性的configurable为true时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false。
- enumerable:当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为false。
2 存取描述符
数据描述符一般是指访问器属性的描述符,具有以下可选键值:
- get:给属性提供getter的方法,如果没有getter则为undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象。
- set:给属性提供setter的方法,如果没有setter则为undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
- configurable:当且仅当该属性的configurable为true时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false。
- enumerable:当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为false。
3 获取属性描述符
通过Object.getOwnPropertyDescriptor() 方法去获取。
Object.getOwnPropertyDescriptor(obj,prop)
作用:获取目标属性的属性描述符。
参数:
- obj:目标对象。
- prop:目标对象上的目标属性。
返回值:目标属性的属性描述符。
let person = {
name: "于家宝",
_age: 18,
};
console.log(Object.getOwnPropertyDescriptor(person, "_age"));
4 设置属性描述符
通过Object.defineProperty() 方法去设置。
Object.defineProperty(obj,prop,descriptor)
作用:在目标对象上定义或者修改一个属性,可以同时修改这个属性的属性描述符。
参数:
- obj:目标对象。
- prop:要定义或者修改的属性名称,是个字符串。
- descriptor:将被定义或者修改的属性描述符。
返回值:目标对象。
let person = {
name: "于家宝",
};
Object.defineProperty(person, "job", {
value: "程序员",
});
console.log(person.job); // 程序员
注意:通过defineProperty() 方法定义的新属性,如果只设置value一个属性描述符,那么这个属性,是不可删除、不可修改、不可枚举的。
这是因为除了value属性描述符,其他的描述符writable、configurable、enumerable默认都是false。
let person = {
name: "于家宝",
age: 18,
};
Object.defineProperty(person, "job", {
value: "程序员", // 不配置writable,configurable,enumerable就都默认false
});
console.log(person.job); // 程序员
person.job = "前端工程师";
delete person.job;
console.log(person.job); // 程序员,不可修改不可删除
for (i in person) {
console.log(i); // name age 没有job 不可枚举
}
4.1 配置writable
此时设置writable为true后该属性就可以修改。
let person = {
name: "于家宝",
};
Object.defineProperty(person, "job", {
value: "程序员",
writable: true,
});
console.log(person.job); // 程序员
person.job = "前端工程师";
console.log(person.job); // 前端工程师
4.2 配置configurable
设置configurable为true后该属性就可以被删除。
let person = {
name: "于家宝",
};
Object.defineProperty(person, "job", {
value: "程序员",
configurable: true,
});
console.log(person.job); // 程序员
delete person.job;
console.log(person.job); // undefined
4.3 configurable的特殊性
还有一点需要注意,属性描述符configurable为true的时候,是可以修改该描述符configurable的,如果为false就无法修改该修饰符,这说明一旦configurable为false就是不可逆的。
- 先设置为true,再修改为false,是可以生效的:
let person = { name: "于家宝", }; Object.defineProperty(person, "job", { value: "程序员", configurable: true, // 先设置为true }); Object.defineProperty(person, "job", { value: "程序员", configurable: false, // 再设置为false }); console.log(person.job); // 程序员 delete person.job; console.log(person.job); // 程序员 没有被删除,说明configurable修改为false成功了
- 先设置为false,再修改为true,后台会报错。
let person = { name: "于家宝", }; Object.defineProperty(person, "job", { value: "程序员", configurable: false, // 先设置为false }); Object.defineProperty(person, "job", { value: "程序员", configurable: true, // 再设置为true,直接报错,configurable为false的时候是不可以修改该属性描述符的 });
4.4 配置enumerable
设置enumerable为true后该属性就可以被枚举。
let person = {
name: "于家宝",
age: 18,
};
Object.defineProperty(person, "job", {
value: "程序员",
enumerable: true,
});
for (i in person) {
console.log(i); // name age job
}
5.同时设置多个属性的属性描述符
通过Object.defineProperties() 方法可以设置多个属性的属性描述符。
Object.defineProperties(obj,props)
作用:在目标对象上定义或者修改一个或多个属性,可以同时修改属性的属性描述符。
参数:
- obj:目标对象。
- props:一个对象,键值对是要定义或修改的属性名和其属性描述符。
返回值:目标对象。
let person = {
name: "于家宝",
age: 18,
};
Object.defineProperties(person, {
job: {
value: "程序员",
enumerable: true,
},
address: {
value: "南京",
enumerable: true,
},
});
for (i in person) {
console.log(i); // name age job address
}