什么是冻结?
JavaScript中对象的冻结指的是防止对象的属性被修改、删除或添加新属性。冻结对象又分为浅冻结与深冻结
对象的浅冻结
用法Object.freeze(obj)
其中obj为要冻结的对象。
js
const obj = { a: 1, b: { c: 2 } };
Object.freeze(obj);
obj.a = 2;
obj.d = 4;
delete obj.b;
console.log(obj)
输出的值为:{ a: 1, b: { c: 2 } },被Object.freeze()冻结的对象无法进行对象属性的新增、修改跟删除。
判断一个对象是否被冻结可使用Object.isFreeze(obj)
,代码示例
js
const obj = { a: 1, b: { c: 2 } };
Object.freeze(obj);
console.log(Object.isFrozen(obj))
输出结果为:true
如果属性的值是对象或者数组类型则会有另外情况,修改属性b的值,代码如下:
js
const obj = { a: 1, b: { c: 2 } };
// shallowFreeze(obj);
Object.freeze(obj);
obj.a = 2; // 不起作用,保持原值1
obj.d = 4;
obj.b.c = 3; // 会起作用,但b对象不是冻结的,所以这会修改原对象
// delete obj.b;
console.log(obj)
输出结果为:{ a: 1, b: { c: 3 } },如果需要对属性b也实现冻结的话,就需要深冻结。
Object.seal()
也用于防止 JavaScript 对象被修改。如果要防止添加新属性和删除现有属性,那么这两种方法都可以满足您的需要。但是,如果要防止现有属性被更改,则必须使用 Object.freeze()。原因就是 Object.seal() 只将现有 configurable 属性标记为不可配置,这意味着只要它们是可写的,就可以更改它们的值。
另外Object.isFrozen()
不能监测到被Object.seal()处理的值,示例如下
js
let obj = { a: 1, b: { c: 2 } };
Object.seal(obj)
obj.a = 2;
obj.d = 4;
obj.b.c = 3;
console.log(obj)
console.log(Object.isFrozen(obj))
输出:
{ a: 2, b: { c: 3 } }
false
对象的深冻结
深度冻结(deep freeze)策略指的是将对象及其所有嵌套对象的属性设置为只读并且不可修改的操作。这样做可以确保对象及其属性在冻结后不能被修改,以提高对象的不变性和安全性。
要实现深度冻结,可以使用Object.freeze()函数。这个函数会递归地冻结给定对象的属性,使其变为只读,并且不能添加、删除或修改属性。 示例如下:
js
const deepFreeze = (obj) => {
Object.freeze(obj);
Object.getOwnPropertyNames(obj).forEach(prop => {
if (typeof obj[prop] === 'object' && obj[prop] !== null) {
deepFreeze(obj[prop]);
}
});
};
const obj = { a: 1, b: { c: 2 } };
deepFreeze(obj);
obj.a = 2; // 不起作用,保持原值1
obj.d = 4;
obj.b.c = 3;
console.log(obj)
输出结果:{ a: 1, b: { c: 2 } }
如何解冻
事实上, 在javascript中, 对象冻结后, 没有办法再解冻, 只能通过克隆一个具有相同属性的新对象, 通过修改新对象的属性来达到目的.
对象复制
js
let obj = { a: 1, b: { c: 2 } };
Object.freeze(obj);
obj = JSON.parse(JSON.stringify(obj))
console.log(Object.isFrozen(obj))
输出值:false。
使用场景
- 防止对象被意外篡改,在开发过程中我们可能会配置一些固定不变的对象或者常量对象,这时候就需要使用到Object.freeze或者定义深冻结方法来确保不可变性,防止被意外修改
- 数据保护,我们需要传递一些数据给其他模块或者函数使用时,为了保证数据的完整性,可以使用对象冻结,防止被修改
- 提高性能,在某些情况下我们可以确定一个对象的属性不会再发生变化,可以使用冻结对象,让JavaScript的引擎在处理对象时更高效。
- 对象比较,在某些情况下,我们需要比较两个对象是否一致,如果都是冻结对象的话,可以通过简单的引用比较来判断它们是否相等,而不需要深度比较对象的属性。
总结
Object.freeze( )
阻止Vue无法实现 响应式系统 当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生"响应",即匹配更新为新的值。但是如果使用 Object.freeze(),这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。