defineProperty

Object.defineProperty() 方法可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

value、writable、enumerable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// value
var obj = {name:'张三', age:19};
var new_obj = Object.defineProperty(obj, "name", {
value:'李四'
})
console.log(obj === new_obj)//true
console.log(obj.name)//张三

// writable
var obj2 = {name:'张三', age:19, id:1101};
var new_obj = Object.defineProperty(obj2, "id", {
writable:false
})
console.log(obj2);
obj2.id = 100;//可以进行赋值,但不会生效
console.log(obj2);//obj.id仍然为1101


给对象某一个属性设置writable属性为false后,修改该属性不会生效(该属性无法被修改)

enumerable

默认情况下Object.defineProperty新添加的属性是不可修改的(不能用obj3.address=”湖南”这种方式进行修改),且不能被for…in和Object.keys方法进行遍历到的。但通过属性赋值操作添加的普通属性是可以被枚举的例如var o = {a:1};o.b=2;那么对象o的b属性是可以被枚举出来的,但用Object.defineProperty添加的新属性默认是不能被枚举和修改的。

1
2
3
4
5
6
7
8
9
10
11

var obj3 = {name:'王五', age:29, id:1102};
var new_obj = Object.defineProperty(obj3, "address", {
writable:false,//该属性值默认就是fasle,所以不写也是一样的效果
enumerable:false,//该属性值默认就是fasle,所以不写也是一样的效果
value:"上海"
})
console.log(obj3);
obj3.address = "北京";//可以进行赋值,但不会生效
console.log(obj3);//obj.address仍然为上海


用Object.defineProperty添加的新属性默认是不能被枚举和修改的

setter、getter

下面这种调用方式会造成无限递归,最终导致栈溢出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var obj = {name:'张三', age:19};
var new_obj = Object.defineProperty(obj, "name", {
get: function(){
console.log("调用了get方法");
return obj['name'];
},
set: function(value){
console.log("调用了set方法");
obj['name'] = value;
}
})
console.log(obj === new_obj)//true
// 注意:调用set和get函数时一定要外面包一层函数,否则会一直递归执行(下面两行代码不能直接执行)
new_obj.name;
obj.name = "李四"

下面这种方式是一种正确使用get、set访问器属性的案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Archiver(temp_init) {
let _temperature = temp_init;//初始化
const archive = [];
Object.defineProperty(this, "temperature", {
get: function() {
console.log("get");
return _temperature;//由于这个_temperature被引用了,导致虽然Archiver执行完了,但里面的_temperature并不会被回收,而是一直保存在内存中
},
set: function(value){
console.log("set");
_temperature = value;
archive.push({val:value})
}
})
this.getArchive = () => archive;//温度归档(每一次修改温度,都会执行set方法,从而向数组archive中push一条记录,且不会被销毁)
}
const arc = new Archiver(30);//初始化温暖
console.log(arc)
arc.temperature = 31;//第一次修改温度
console.log(arc.temperature)


set和get的正确使用方法

defineProperty
https://zbdev.online/2022/04/22/defineProperty/
作者
zzb
发布于
2022年4月22日
许可协议