浅拷贝冻结对象能得到可修改的新对象,因为浅拷贝创建的是未冻结的普通对象,而非解除原对象冻结状态;新对象属性默认可写可配置,但嵌套引用仍共享。

无法对已冻结对象(Object.freeze() 后的对象)进行浅拷贝并得到一个可修改的副本——因为浅拷贝操作(如 Object.assign()、展开运算符 {...obj}、Array.from() 等)**只复制属性值,不解除原对象的冻结状态**;而冻结是对象自身的元属性(`[[Extensible]] = false`, `writable: false`, `configurable: false`),这些特性不会被浅拷贝继承,但新对象默认是可扩展、可配置的——关键在于:浅拷贝本身能成功,但结果不是“解冻”,而是创建一个**新的、未冻结的普通对象**。
浅拷贝冻结对象的本质行为
冻结(Object.freeze(obj))只是让 obj 无法被修改,并不影响其他对象。当你对它做浅拷贝时:
- 拷贝的是属性的**当前值**(基本类型值被复制,引用类型值被共享)
- 新对象是一个全新对象,其内部属性默认是
writable: true、configurable: true、对象自身extensible: true - 原对象是否冻结,和新对象是否冻结完全无关 —— 浅拷贝不会把“冻结”这个状态复制过去
常见浅拷贝方式对冻结对象的实际效果
以下操作均能「成功执行」,且返回一个可修改的新对象(即看起来“解冻”了,实则是新建了一个普通对象):
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
-
const copy = { ...frozenObj };→ 新对象可增删改属性 -
const copy = Object.assign({}, frozenObj);→ 同上,可修改 -
const copy = structuredClone(frozenObj);(ES2022+)→ 返回深拷贝,且新对象默认未冻结(注意:structuredClone不保留冻结状态) -
const copy = JSON.parse(JSON.stringify(frozenObj));→ 仅适用于纯数据对象(会丢函数、undefined、Symbol、Date 等)
重要提醒:别混淆「拷贝后可修改」和「解冻原对象」
有人误以为“拷贝后能改,说明原对象被解冻了”——这是错误理解:
-
Object.isFrozen(frozenObj) === true始终成立,无论你拷贝多少次 -
Object.isFrozen(copy) === false(除非你手动再调用Object.freeze(copy)) - 若原对象含嵌套对象(如
frozenObj.nested = { x: 1 }),浅拷贝后copy.nested和frozenObj.nested指向同一对象 → 修改copy.nested.x会影响原对象的nested.x(因为嵌套对象本身可能也被冻结)
如果目标是「获得一个可修改的完整副本」
那就按需选择:
- 纯数据对象(无函数、无循环引用)→ 用
JSON.parse(JSON.stringify()) - 现代环境 + 支持
structuredClone→ 推荐,能处理 Date、Map、Set、RegExp 等 - 需要兼容旧环境或自定义逻辑 → 手写递归深拷贝,或使用 Lodash 的
_.cloneDeep() - 仅需一层可修改 → 浅拷贝(展开符 /
Object.assign)已足够,无需额外操作
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










