Object.defineProperty是一个用于定义或修改对象属性的方法。它提供了一种更底层和灵活的方式来定义属性,可以设置属性的配置(如可枚举性、可配置性、可写性等),并且可以定义属性的getter和setter函数。
语法:
Object.defineProperty(obj, prop, descriptor)
参数说明:
- `obj`:要定义属性的对象
- `prop`:要定义或修改的属性名称。
- `descriptor`:一个描述符对象,用于定义或修改属性的特性。它有以下可选的键值:
- `value`:属性的值,默认为`undefined`。
- `writable`:属性的可写性。默认为`false`,即该属性为只读属性。
- `enumerable`:属性的可枚举性。默认为`false`,即该属性不可枚举。
- `configurable`:属性的可配置性。默认为`false`,即该属性不可被删除。
- `get`:获取属性值的函数。
- `set`:设置属性值的函数。
直接看代码:
没有设置writable、enumerable、configurable属性,默认都为false,age属性不可枚举,不可修改,不可删除。
let person = {
name: "张三",
sex: "男",
};
Object.defineProperty(person, 'age', {
value: 18,
})
console.log(person); // {name: '张三', sex: '男', age: 18}
for (p in person) { // 这里由于Object.defineProperty中没有设置enumerable:true,所以age属性不会参与枚举遍历
console.log(p);
// name
// sex
}
person.age = 19; // 这里由于Object.defineProperty中没有设置writable:true,所以修改不会生效
console.log(person); // {name: '张三', sex: '男', age: 18}
delete person.age; // 这里由于Object.defineProperty中没有设置configurable:true,所以删除不会生效
console.log(person); // {name: '张三', sex: '男', age: 18}
此时修改是person对象上的age值是无效的,值实际上没有更新
设置了writable、enumerable、configurable属性的值为true之后,age属性可以被枚举,可以被修改,可以被删除。
let person = {
name: "张三",
sex: "男",
};
Object.defineProperty(person, "age", {
value: 18,
enumerable: true, //控制属性是否可以枚举,默认值是false
writable: true, //控制属性是否可以被修改,默认值是false
configurable: true, //控制属性是否可以被删除,默认值是false
});
console.log(person); // {name: '张三', sex: '男', age: 18}
for (p in person) {
// 这里由于Object.defineProperty中设置了enumerable:true,所以age属性参与了枚举遍历
console.log(p);
// name
// sex
// age
}
person.age = 19; // 这里由于Object.defineProperty中设置了writable:true,所以修改生效了
console.log(person); // {name: '张三', sex: '男', age: 19}
delete person.age; // 这里由于Object.defineProperty中设置了configurable:true,所以删除生效了
console.log(person); // {name: '张三', sex: '男'}
Object.defineProperty 还可以设置getter和setter方法
let number = 18;
let person = {
name: "张三",
sex: "男",
};
// 此外 Object.defineProperty 还可以设置getter和setter方法
Object.defineProperty(person, "age", {
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true, //控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get() {
console.log("有人读取age属性了");
return number;
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value) {
console.log("有人修改了age属性,且值是", value);
number = value;
},
});
console.log('person', person);
console.log('number', number);
注意事项:
Object.defineProperty() 设置了getter和setter方法之后,就不能再设置value属性,否则控制台报错:Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>