Object.freeze()是什么

看一下以下这段代码

var constantize = (obj) => {
  Object.freeze(obj); 
  Object.keys(obj).forEach((key) => {
    if (typeof obj[key] === 'object' && obj[key] !== null) {
      constantize(obj[key]);
    }
  });
};

Object.freeze() 是 JavaScript 中用于冻结对象的方法。冻结后的对象变得不可变,不能添加、删除或修改其属性。你结合 Object.freeze() 实现的 constantize 函数,能够递归地冻结一个对象及其所有嵌套的对象。

Object.freeze() 的具体作用

  1. 冻结对象:一旦对象被 Object.freeze() 冻结,无法对该对象的属性做任何修改。

    • 不能修改属性值
    • 不能添加新属性
    • 不能删除属性
    • 不能重新定义属性的描述符(例如,将某个属性从可枚举变为不可枚举等)。
  2. 非深度冻结Object.freeze() 只会冻结对象的顶层属性。如果对象的属性是另一个对象,那么内部的嵌套对象不会自动冻结。这就是为什么在你的 constantize 函数中,递归冻结是必要的。

冻结对象后的行为

  • 尝试修改冻结对象的属性不会报错(在严格模式下会抛出错误),但不会有任何效果。
  • 可以读取冻结对象的属性。

示例:

let obj = { prop: 42 };
Object.freeze(obj);

obj.prop = 33;   // 无效操作,值不会改变
console.log(obj.prop);  // 输出: 42

Object.freeze() 的主要特性:

  1. 属性不可写(writeable: false):冻结后,所有的属性变为不可写。
  2. 属性不可配置(configurable: false):属性描述符也不可更改,不能删除或重新配置这些属性。
  3. 不可扩展(extensible: false):不能向对象添加新的属性。

深度冻结与递归处理:结合的 constantize 函数

代码通过递归调用 constantize,实现了对对象的深度冻结,即不仅冻结对象的顶层属性,还会冻结它的所有嵌套属性。

var constantize = (obj) => {
  Object.freeze(obj); // 冻结当前对象

  // 遍历对象的所有键,检查其值是否为对象
  Object.keys(obj).forEach((key) => {
    // 如果对象的某个属性是对象,且不为 null,则递归冻结
    if (typeof obj[key] === 'object' && obj[key] !== null) {
      constantize(obj[key]); // 递归调用,冻结嵌套对象
    }
  });
};

详细解释代码中的 Object.freeze() 作用

  1. Object.freeze(obj)

    • 该语句冻结传入的对象 obj,使得它的顶层属性不可变。
    • 例如,如果传入的对象是 { a: 1, b: { c: 2 } },那么对象的属性 ab 将被冻结,不能被修改。
  2. Object.keys(obj)

    • 获取对象的所有可枚举属性名。通过 forEach 遍历这些属性,处理每个属性的值。
  3. 递归调用 constantize(obj[key])

    • 如果对象的某个属性 obj[key] 是另一个对象,那么 constantize 递归调用自身,将该嵌套对象也进行冻结。
    • 这样可以确保嵌套的对象(例如 { b: { c: 2 } } 中的 b 对象)也被冻结,无法修改。

constantize 的执行流程

以如下对象为例:

let obj = {
  a: 1,
  b: {
    c: 2,
    d: {
      e: 3
    }
  }
};

constantize(obj);
  1. 第一步:冻结对象 obj。这将使得 obj.aobj.b 这两个顶层属性无法修改、删除或重新定义。
  2. 第二步:检查 obj.b 是否是对象。因为 obj.b 是对象,所以递归调用 constantize(obj.b)
  3. 第三步:冻结 obj.b,使得 b.cb.d 也无法修改。
  4. 第四步:检查 obj.b.d 是否是对象。因为 obj.b.d 是对象,所以再次递归调用 constantize(obj.b.d)
  5. 第五步:冻结 obj.b.d,最终使得 d.e 也无法修改。

此时,整个对象 obj 及其所有嵌套的对象都被冻结,不能再被修改。

递归冻结的意义

Object.freeze() 只能冻结对象的顶层属性。如果对象包含嵌套对象,内部的嵌套对象依然可以被修改。例如:

let obj = { a: 1, b: { c: 2 } };
Object.freeze(obj);

obj.a = 10; // 无法修改,冻结生效
obj.b.c = 20; // 可以修改,因为 obj.b 没有被冻结

为了避免这种情况,constantize 通过递归调用,确保所有嵌套的对象都被冻结,从而实现深度不可变。

总结

  • Object.freeze():用于冻结对象,使其属性不能被修改、删除或添加新的属性。
  • 非深度冻结Object.freeze() 只能冻结对象的顶层属性,对于嵌套对象需要递归处理。
  • constantize 函数:通过递归调用 Object.freeze(),实现对象及其嵌套对象的深度冻结,确保整个对象结构的不可变性。

constantize 是一个实用的工具函数,适合用于需要递归冻结复杂嵌套对象的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值