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(),这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
A黄俊辉A2 天前
uniapp webview中实现 app和内嵌的H5双向通信
vue.js·json
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄2 天前
JavaScript 隐式全局变量解析
javascript
honkun62 天前
vue 表格组件 vxe-table 配置 ajax 请求自动加载数据与表单查询
vue.js·vxe-table
kybs19912 天前
全球灾害数据分析可视化 毕业设计-附源码66794
vue.js·spring boot·mysql·安全·django·c#·asp.net