javaScript Object对象方法defineProperty
作用:在一个对象上定义一个新属性,或者修改一个对象现有的属性,然后返回该对象
一、对象的描述符
1.1 configurable
当该对象的configurable=true的时候,该对象的描述符才能够被改变,属性也能删除。默认为false
1.2 enumerable
当enumerable=true时,该属性才会出现在对象的枚举属性中,即:**console.log(对象)**的时候可不可见。
1.3 value
表示该属性对应的值,可以是任何有效的JavaScript值
1.4 writable
当writable=true,上面的value才能被赋值运算符改变。默认为false。
1.5 get
访问该对象对应的属性时进行拦截并且调用的函数
1.6 set
修改该对象对应的属性时进行拦截并且调用的函数
1.7 描述符分类
configurable | enumerable | value | writable | get | set | |
|---|---|---|---|---|---|---|
| 数据描述符 | 可以 | 可以 | 可以 | 可以 | 不可以 | 不可以 |
| 存取描述符 | 可以 | 可以 | 不可以 | 不可以 | 可以 | 可以 |
二、defineProperty使用场景
2.1 基本使用场景
const obj = {};
Object.defineProperty(obj, "key", {
value: 10,
writable: true,
enumerable: true,
configurable: true
});
obj.key = 12;
console.log(obj);
/* 结果
{
"key": 12
}
*/
2.2 writable
Object.defineProperty(obj, "value", {
value: "lucy",
writable: false,
enumerable: true,
configurable: true
});
obj.value = "jam"; // 这行不生效,不可写,即:修改
console.log(obj);
/* 结果
{
"key": 12,
"value": "lucy"
}
*/
2.3 enumerable=false
Object.defineProperty(obj, "grade", {
value: "A",
writable: true,
enumerable: false,
configurable: true
});
console.log(obj);
for(let key in obj) {
console.log(key);
}
/* 输出结果
key
value
// 由于grade不可枚举,因此不会打印出来
*/
console.log(Object.keys(obj));
/* 输出结果
[
"key",
"value"
]
*/
2.4 configurable=false
const obj1 = {};
Object.defineProperty(obj1, "key", {
value: "haha",
configurable: false
});
Object.defineProperty(obj1, "key", {
value: "haha",
configurable: true
}); //直接报错
Object.defineProperty(obj1, "key", {
value: "haha1",
enumerable: true
}); //直接报错
2.5 自定义setters和getters
固定set、get值设置
const obj2 = {};
Object.defineProperty(obj2, "name", {
get() {
return "想获取名称?没门!";
},
set(val) {
console.log(`想把名称该为${val}?没门!`);
}
});
console.log(obj2.name); // 想获取名称?没门!
obj2.name = "古政"; // 想把名称该为古政?没门!
可变get、set设置。
const obj3 = {};
var value = 18;
Object.defineProperty(obj3, "age", {
get() {
return value;
},
set(newVal) {
value = newVal;
}
});
console.log(obj3.age); // 18
obj3.age = 22; // 修改成功
console.log(obj3.age); // 22
重点:可能会造成疑惑的写法
const obj4 = {
age: 18
};
var value = obj4.age;
Object.defineProperty(obj4, "age", {
get() {
return value;
},
set(newVal) {
value = newVal;
}
});
console.log(obj4.age); // 18
obj4.age = 22; // 修改成功
console.log(obj4.age); // 22
笔者第一次学习手写Vue的双向绑定中,便遇到了以上的写法,当时一直想不明白,为什么set中修改了value后,可以直接修改掉obj4.age的内容?原理如下:
- 第一步,console.log(obj4.age)时,会调用get方法获取到value
- 第二步,obj4.age = 22后,value发生了改变,变为22
- 第三步,console.log(obj4.age),注意!!这个时候并不是获取obj4中的age值,而是value的值
- 总结:其实就是value做了一个闭包,使得后续的value值,服务于obj4对象中的age属性。 可以通过以下的图解,更好的了解。
二、defineProperties使用场景
作用:其实就是一个函数,定义多个属性,基本的内容以及原理与defineProperty相同。使用案例如下:
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
});