浅拷贝无法防止嵌套对象属性被篡改,因其仅复制第一层属性,引用类型仍共享内存地址;真正防护需依场景选方法:只读不拷贝、改顶层用浅拷贝、改嵌套必用深拷贝(如structuredclone)。

浅拷贝本身无法防止嵌套对象属性被篡改——这是它固有的限制。所谓“防止”,不是靠浅拷贝实现,而是靠**识别场景、选对方法、主动隔离**。
为什么浅拷贝防不住嵌套修改
浅拷贝只复制对象第一层属性的值:基本类型(如字符串、数字)会生成独立副本;但引用类型(如子对象、数组)复制的是内存地址,新旧对象仍指向同一块堆内存。一旦修改 b.user.name,a.user.name 也会变。
例如:
const a = { id: 1, user: { name: 'Alice' } };
const b = { ...a }; // 浅拷贝
b.user.name = 'Bob';
console.log(a.user.name); // 'Bob' —— 原对象已被篡改
真正能防嵌套篡改的三种做法
关键不在于“怎么浅拷贝”,而在于“要不要浅拷贝”:
-
只读使用时,无需拷贝:如果函数只读取嵌套字段(如
config.api.timeout),直接传原对象即可,不改就不污染 -
需修改顶层字段,用浅拷贝足够:比如更新
options.method或options.headers这类一级属性,{...obj} 安全且高效 -
要改嵌套字段或调用 push/splice 等方法,必须升为深拷贝:此时
structuredClone(obj)是现代首选(支持 Date、Map、Set、循环引用),老环境可用lodash.cloneDeep
临时规避嵌套风险的小技巧
若暂时无法升级到深拷贝,又必须局部修改嵌套结构,可手动重建受影响分支:
- 用展开运算符逐层解构:
const safeCopy = { ...obj, user: { ...obj.user, name: 'NewName' } }; - 对数组内嵌对象,避免直接改
arr[0].prop,改用arr.map((item, i) => i === 0 ? { ...item, prop: newVal } : item) - 函数入参前做防御性检查:
if (typeof obj?.user === 'object' && obj.user !== null) {...},提前拦截非法结构
别踩这些常见坑
很多“看似安全”的写法其实无效:
- 不用 JSON.parse(JSON.stringify(obj)):会丢掉函数、undefined、Symbol、RegExp、Date,且无法处理循环引用
- 不用 Object.assign(null, obj):target 为 null 会被强制转为空对象,但语义混乱,易出错
- 不依赖第三方 shallowClone 工具包:除非明确标注支持嵌套保护,否则多数仍是纯浅拷贝
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











