关于 Object.defineProperty()
通常,定义或者修改一个JS对象,有以下方式:
// 1. 字面量
let obj = {
name: 'cedric',
age: 18
}
// 2. new Object()
let obj = new Object()
obj.name = 'cedric'
obj.age = 18
// 3. Object.create()
// 4. 工厂模式
// 5. 构造函数
// 6. ...
上面当对象创建一个属性后,如:obj.name = 'cedric'
, 其中 name 就是一个 【普通属性】,ta的值允许修改或删除,也可以通过for..in
或 Object,keys
枚举遍历。
如果要更精准的控制对象属性,可以使用 Object.defineProperty()
方法。
语法
Object.defineProperty(obj, prop, descriptor)
// obj: 需要定义属性的当前对象
// prop: 当前需要定义或修改的属性名
// descriptor: 属性描述符
例如:
let obj = {}; // 创建一个新对象
// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(obj, "name", {
value : 'cedric', // 属性 value 的初始化值 cedric
writable : true, // 可修改值内容, 默认值 false
enumerable : true, // 可枚举,默认 false
configurable : true // 可枚举,默认 false
});
属性描述符 - descriptor
属性 | 说明 | 默认值 |
---|---|---|
configurable | 该属性为true时才可以被删除 | false |
enumerable | 为true时,可以被for...in或Object.keys枚举 | false |
value | 该属性对应的值 | undefined |
writable | 为true时,value才能被赋值运算符改变 | false |
get | 取值的时候,触发 | undefined |
set | 修改属性的时候,触发 | undefined |
set 和 get
设置set或者get,就不能在设置value和wriable,否则会报错。
let obj = {
__age: 18
};
Object.defineProperty(obj, 'age', {
enumerable: true,
configurable: true,
get: function () {
console.log('get------------age');
return 'My age is ' + this.__age;
},
set: function (newVal) {
console.log('set------------age', newVal);
this.__age = newVal;
}
});
console.log(obj.__age); // 18, __age为普通属性
console.log(obj.age); // My age is 18 , 触发 get()
obj.age = 22; // 触发 set()
console.log(obj.__age); // 22
console.log(obj.age); // My age is 22, 触发 get()
obj.__age = 33; // 既不触发 set() , 也不触发 get()
console.log(obj.__age); // 33
console.log(obj.age); // My age is 33 , 触发 get()
👉 注意
1. 默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改的
let obj = {};
Object.defineProperty(obj, "age", {
value : '18',
});
console.log(obj.age); // 18
obj.age = 20;
console.log(obj.age); // 18
2. configurable 可以看做是所有属性描述符的总开关,一旦设置为 false 后(如果不设置,默认值也是 false),后面所有描述符就都不能被改变了。
如果第一次不设置 configurable,或者设置为 false, 第二次再设置 configurable, 就会报错。
let obj = {};
Object.defineProperty(obj, "age", {
value : '18',
configurable:false
});
Object.defineProperty(obj, "age", {
value : '18',
configurable:true
});
// error: Uncaught TypeError: Cannot redefine property: age
3. 表格里面的几个描述符是不允许同时存在的
描述符壳同时具有的键值:
configurable | enumerable | value | writable | get | get |
---|---|---|---|---|---|
数据描述符 | Yes | Yes | Yes | Yes | No |
存取描述符 | Yes | Yes | No | No | Yes |