JS 浅冻结与深冻结对象、解冻对象

什么是冻结?

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。

使用场景

  1. 防止对象被意外篡改,在开发过程中我们可能会配置一些固定不变的对象或者常量对象,这时候就需要使用到Object.freeze或者定义深冻结方法来确保不可变性,防止被意外修改
  2. 数据保护,我们需要传递一些数据给其他模块或者函数使用时,为了保证数据的完整性,可以使用对象冻结,防止被修改
  3. 提高性能,在某些情况下我们可以确定一个对象的属性不会再发生变化,可以使用冻结对象,让JavaScript的引擎在处理对象时更高效。
  4. 对象比较,在某些情况下,我们需要比较两个对象是否一致,如果都是冻结对象的话,可以通过简单的引用比较来判断它们是否相等,而不需要深度比较对象的属性。

总结

Object.freeze( ) 阻止Vue无法实现 响应式系统 当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生"响应",即匹配更新为新的值。但是如果使用 Object.freeze(),这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。

相关推荐
颜酱1 小时前
07 | 把字段与指标同步到 Qdrant(生成阶段)
前端·人工智能·后端
用户059540174461 小时前
把AI长期记忆测试从手动验证换成pytest,2天揪出11个隐藏Bug
前端·css
Larcher2 小时前
从“加载模型”界面到端侧推理:拆解一个 React + WebGPU 大模型 Demo
javascript·后端
Larcher2 小时前
从状态快照到惰性初始化:读懂 React useState 的三个关键场景
javascript·人工智能·后端
lichenyang4532 小时前
从 Vite 空项目到 AIGC 图片工作台:我如何打通生图、任务轮询、生成库与 Canvas 动态特效
前端·人工智能
泡沫冰@3 小时前
上章节中文件的讲解
前端·网络·nginx
进击的丸子3 小时前
APP人脸识别增值版Harmony Demo实操与关键代码解析
前端·程序员·harmonyos
a1117763 小时前
唯美花朵风格的黑胶唱片音乐播放器
前端·css·css3
Hilaku4 小时前
工作 5 年后,决定你薪资上限的究竟是什么?
前端·javascript·程序员
爱分享的程序猿-Clark4 小时前
【前端分享】vue3 有 keep-alive属性吗?
前端