JS怎么冻结对象?创建不可变对象有哪些常用方法

来源:草根站长作者:松松建站头衔:草根站长
导读:本期聚焦于小伙伴创作的《JS怎么冻结对象?创建不可变对象有哪些常用方法》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JS怎么冻结对象?创建不可变对象有哪些常用方法》有用,将其分享出去将是对创作者最好的鼓励。

在JavaScript开发中,对象默认是可变的,我们可以随意添加、修改、删除对象的属性,这种特性在某些场景下会引发意外的数据篡改问题。为了避免这种情况,JS提供了多种对象冻结方法,帮助开发者创建不可变对象,保障数据的稳定性。

JS怎么冻结对象?创建不可变对象有哪些常用方法

JS常用的对象冻结方法

JS内置了三个用于限制对象修改的方法,它们的限制程度从低到高依次是Object.preventExtensionsObject.sealObject.freeze,下面分别介绍每个方法的特性。

1. Object.preventExtensions

这个方法的作用是禁止对象添加新的属性,但是已有的属性可以被修改或者删除。

// 创建一个普通对象
const obj1 = { name: '张三', age: 20 };

// 禁止对象扩展
Object.preventExtensions(obj1);

// 尝试添加新属性,严格模式下会报错,非严格模式下静默失败
obj1.gender = '男';
console.log(obj1.gender); // undefined

// 可以修改已有属性
obj1.age = 21;
console.log(obj1.age); // 21

// 可以删除已有属性
delete obj1.name;
console.log(obj1.name); // undefined

// 判断对象是否不可扩展
console.log(Object.isExtensible(obj1)); // false

2. Object.seal

这个方法在Object.preventExtensions的基础上,进一步禁止删除对象的已有属性,但是已有属性的值仍然可以被修改。

// 创建一个普通对象
const obj2 = { name: '李四', age: 25 };

// 密封对象
Object.seal(obj2);

// 尝试添加新属性,静默失败
obj2.gender = '女';
console.log(obj2.gender); // undefined

// 尝试删除已有属性,静默失败
delete obj2.name;
console.log(obj2.name); // 李四

// 可以修改已有属性
obj2.age = 26;
console.log(obj2.age); // 26

// 判断对象是否被密封
console.log(Object.isSealed(obj2)); // true

3. Object.freeze

这是限制程度最高的方法,它会完全冻结对象:不能添加新属性、不能删除已有属性、不能修改已有属性的值,同时对象本身也不能被修改原型。

// 创建一个普通对象
const obj3 = { name: '王五', age: 30 };

// 冻结对象
Object.freeze(obj3);

// 尝试添加新属性,静默失败
obj3.gender = '男';
console.log(obj3.gender); // undefined

// 尝试删除已有属性,静默失败
delete obj3.name;
console.log(obj3.name); // 王五

// 尝试修改已有属性,静默失败
obj3.age = 31;
console.log(obj3.age); // 30

// 判断对象是否被冻结
console.log(Object.isFrozen(obj3)); // true

浅冻结与深冻结的区别

需要注意的是,Object.freeze默认是浅冻结,也就是说如果对象的属性值本身是对象或者数组,那么这个属性值内部的内容还是可以被修改的。

const obj4 = {
  name: '赵六',
  hobbies: ['吃饭', '睡觉']
};

// 浅冻结对象
Object.freeze(obj4);

// 修改基本类型属性,静默失败
obj4.name = '钱七';
console.log(obj4.name); // 赵六

// 修改引用类型属性的内部内容,修改成功
obj4.hobbies.push('打游戏');
console.log(obj4.hobbies); // ['吃饭', '睡觉', '打游戏']

如果需要实现深冻结,也就是让对象所有层级的属性都不可修改,就需要递归遍历对象的所有属性,对每个属性值如果是对象或数组的话也执行Object.freeze

// 深冻结函数
function deepFreeze(target) {
  // 获取对象所有自身属性的属性名
  const propNames = Object.getOwnPropertyNames(target);

  // 先冻结自身
  Object.freeze(target);

  // 遍历所有属性
  for (const name of propNames) {
    const value = target[name];
    // 如果属性值是对象或者数组,且不为null,就递归冻结
    if (value && typeof value === 'object') {
      deepFreeze(value);
    }
  }
  return target;
}

const obj5 = {
  name: '孙八',
  hobbies: ['看书', '跑步'],
  info: { address: '北京' }
};

// 深冻结对象
deepFreeze(obj5);

// 修改引用类型属性的内部内容,静默失败
obj5.hobbies.push('游泳');
console.log(obj5.hobbies); // ['看书', '跑步']

obj5.info.address = '上海';
console.log(obj5.info.address); // 北京

三种方法的对比

为了更清晰地了解三个方法的区别,我们可以通过下面的表格对比它们的特性:

方法禁止添加属性禁止删除属性禁止修改属性值影响层级
Object.preventExtensions仅当前对象
Object.seal仅当前对象
Object.freeze(浅)仅当前对象的第一层属性
Object.freeze(深,递归实现)对象所有层级的属性

使用场景建议

在实际开发中,我们可以根据需求选择合适的方法:

  • 如果只需要禁止对象添加新属性,允许修改和删除已有属性,使用Object.preventExtensions
  • 如果需要禁止添加和删除属性,但是允许修改已有属性的值,使用Object.seal
  • 如果需要完全冻结对象的第一层属性,使用Object.freeze
  • 如果对象包含多层嵌套的引用类型属性,需要所有层级都不可修改,就使用递归实现的深冻结方法

需要注意的是,这些冻结方法在严格模式下,对对象的违规操作会直接抛出错误,非严格模式下只会静默失败,所以建议在开发时开启严格模式,方便及时发现问题。

Object_freezeObject_sealObject_preventExtensions不可变对象修改时间:2026-06-23 15:03:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。