本文详解 JavaScript 中数组赋值时因引用传递导致的“反向修改”问题,揭示 obj.a = obj.b 实际共享内存的本质,并提供多种可靠深拷贝方案(如扩展运算符、slice()、Array.from() 等),避免意外的数据污染。
本文详解 javascript 中数组赋值时因引用传递导致的“反向修改”问题,揭示 `obj.a = obj.b` 实际共享内存的本质,并提供多种可靠深拷贝方案(如扩展运算符、`slice()`、`array.from()` 等),避免意外的数据污染。
在 JavaScript 中,数组和对象属于引用类型(reference types),这意味着变量存储的并非数据本身,而是指向内存中实际数据的地址。当执行 obj.var1 = obj.var2 时,你并未创建新数组,而是让 var1 和 var2 同时指向同一个数组实例。后续对任一变量所指数组的修改(例如 obj.var1[1] = 99),都会反映在另一个变量上——这正是示例中“恢复失败”的根本原因:obj.var1 = obj.var2 并未还原原始值,而只是重新建立了对同一被污染数组的引用。
以下代码清晰复现该问题:
const obj = {
var1: [],
var2: []
};
obj.var1 = [1, 10, 1];
obj.var2 = obj.var1; // ❌ 浅赋值:var2 指向 var1 所指的同一数组
obj.var1 = [0, 2, 0]; // 新调用,覆盖 var1(不影响 var2,仍指向原数组)
obj.var1 = obj.var2; // ❌ 再次浅赋值:var1 重新指向原数组 → 此时 var1 和 var2 共享同一引用
obj.var1[1] = 99; // 修改索引 1 → 同时影响 var1 和 var2!
console.log(obj.var1); // [1, 99, 1]
console.log(obj.var2); // [1, 99, 1] ← 意外被修改!✅ 正确做法是进行浅拷贝(shallow copy)——对一维数组而言,这已足够隔离变更。推荐以下安全写法(均生成新数组实例):
// 方案1:扩展运算符(ES6+,最常用、可读性佳) obj.var1 = [...obj.var2]; // 方案2:Array.prototype.slice() obj.var1 = obj.var2.slice(); // 方案3:Array.from() obj.var1 = Array.from(obj.var2); // 方案4:concat()(空数组拼接) obj.var1 = obj.var2.concat();
⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 上述方法仅适用于一维数组(即元素均为基本类型)。若数组嵌套对象或子数组,需使用 structuredClone()(现代环境)或第三方库(如 Lodash 的 _.cloneDeep())进行深拷贝;
- 避免使用 JSON.parse(JSON.stringify(arr)) 处理含函数、undefined、Date、RegExp 等特殊值的数组,因其会丢失类型或抛出错误;
- 在函数式编程或状态管理(如 React)中,始终优先采用不可变更新模式,杜绝直接修改原数组。
总结:理解“引用 vs 值”是驾驭 JavaScript 数据操作的关键。= 永远不复制数组内容,只复制引用;要真正“备份”数组,请务必使用显式拷贝方法。养成检查赋值语义的习惯,可大幅减少隐蔽的数据同步 Bug。










