😄 从Object.defineProperty
说起
使用Object.defineProperty
可以给对象定义属性,同时可以给当前属性定义是否可配置,可写,可枚举等特性。比如
const a = {}
Object.defineProperty(a, "p", {
value: 123,
configurable: true,
writable:true,
enumerable: true
})
上面的代码给对象a
定义了一个p
属性,同时通过data descriptor定了特性。这里主要关注两个描述符字段:configurable
和writable
。
configurable
:可配置,表示属性是否可以删除,或者重新配置当前data descriptor
的值writable
:可写,表示是否可以给属性重新赋值
Object.preventExtensions
是防止对象新增属性,也防止对象的原型被重新赋值。
const o1 = {};
Object.preventExtensions(o1);
try {
Object.defineProperty(o1, 'p1', {
value: 111
});
} catch (e) {
console.log(e);
// TypeError: Cannot define property p1, object is not extensible
}
这里可以看到,如果给o1
添加新的属性p1
就会报object is not extensible
的错误,此时o1
不可扩展。
可以通过Object.isExtensible()
来判断是否被prevent
Object.isExtensible(o1) // true
Object.seal
的效果相当于: 在Object.defineProperty
时将configurable
设置成false
,同时对对象调用Object.preventExtensions
。但是原有的属性值是可以修改的。
(function(){
// 必须在严格模式下 才有产生error 否则 静默失败
"use strict";
const o2 = { p2: "hello world" }
Object.seal(o2)
try {
delete o2.p2
} catch (e) {
console.log(e) // Cannot delete property 'p2' of #<Object>
}
try {
o2.p3 = 'p3' // Cannot add property p3, object is not extensible
} catch (e) {
console.log(e)
}
o2.p2 = 'newValue' // 修改成功
// 此时的 o2 { p2: "newValue" }
})()
必须在严格模式下才会报错, 否则只是静默失败
可以通过Object.isSealed()
来判断是否被seal
😆 Object.freeze
Object.freeze
是在Object.seal
的基础上再防止属性值被修改,将属性都变成 只读型(Readonly)。
如果重新在运行上面的代码,会发现 o2.p2 = 'newValue'
也会产生错误:
(function(){
// 必须在严格模式下 才有产生error 否则 静默失败
"use strict";
const o2 = { p2: "hello world" }
Object.seal(o2)
try {
delete o2.p2
} catch (e) {
console.log(e) // Cannot delete property 'p2' of #<Object>
}
try {
o2.p3 = 'p3'
} catch (e) {
console.log(e) // Cannot add property p3, object is not extensible
}
try {
o2.p2 = 'newValue' // 修改失败
} catch (e) {
console.log(e) // Cannot assign to read only property 'p2' of object '#<Object>
}
// 此时的 o2 { p2: "hello world" }
})()
可以使用Object.isFrozen
来判断是否被freeze
🤩 Object.preventExtensions
vs Object.seal
vs Object.freeze
从上面可以看出,这三个方法对 对象的保护程度 是依次递增的。
Object.preventExtensions
只防止添加属性,不可扩展Object.seal
除了不可扩展,也不可配置Object.freeze
就像freeze的意思是被冻结,不可扩展,不可配置,不可重写。