
本文详解 JavaScript 中数组赋值的本质是引用传递,解释为何修改 obj.var1[1] 后恢复 obj.var1 = obj.var2 无法还原原始值,并提供安全的浅拷贝与深拷贝实践方案。
本文详解 javascript 中数组赋值的本质是引用传递,解释为何修改 `obj.var1[1]` 后恢复 `obj.var1 = obj.var2` 无法还原原始值,并提供安全的浅拷贝与深拷贝实践方案。
在 JavaScript 中,数组(以及对象、函数等)属于引用类型(reference type),而非基本类型(如 number、string、boolean)。这意味着变量存储的并非数据本身,而是指向内存中实际数据的引用(reference)。当执行 obj.var1 = obj.var2 时,你并未复制数组内容,而是让 var1 和 var2 共同指向同一个数组实例。因此,对任一变量所指向数组的任何修改(例如 obj.var1[1] = 99),都会实时反映在另一个变量上——这正是示例中“反向复制”错觉的根源:看似在“恢复”,实则两个属性始终共享同一份底层数据。
以下代码清晰复现该问题:
var obj = {
var1: [],
var2: []
};
obj.var1 = [1, 10, 1];
obj.var2 = obj.var1; // ⚠️ 引用赋值:var2 指向与 var1 相同的数组
obj.var1 = [0, 2, 0]; // 创建新数组,var1 指向新地址;var2 仍指向原数组 [1,10,1]
obj.var1 = obj.var2; // ✅ 此时 var1 重新指向原数组 → 输出 [1,10,1]
console.log("1.", "var1 =", obj.var1, "var2 =", obj.var2); // [1,10,1], [1,10,1]
obj.var1[1] = 99; // ⚠️ 修改原数组的索引1 → 影响所有引用它的变量!
console.log("After mutation:", "var1 =", obj.var1, "var2 =", obj.var2); // [1,99,1], [1,99,1]
obj.var1 = obj.var2; // ❌ 再次赋值无意义:两者本就指向同一数组
console.log("2.", "var1 =", obj.var1, "var2 =", obj.var2); // 仍是 [1,99,1], [1,99,1]✅ 正确做法:避免引用共享,使用拷贝(copy)而非赋值(assignment)
对于一维数组(即不包含嵌套对象/数组),推荐使用浅拷贝(shallow copy):
立即学习“Java免费学习笔记(深入)”;
- 展开运算符(Spread Syntax):obj.var1 = [...obj.var2];
- Array.from():obj.var1 = Array.from(obj.var2);
- slice():obj.var1 = obj.var2.slice();
- concat():obj.var1 = obj.var2.concat();
// 安全恢复示例
obj.var1 = [1, 10, 1];
obj.var2 = [...obj.var1]; // ✅ 浅拷贝:创建新数组,内容相同但内存独立
obj.var1[1] = 99;
console.log("After mutation:", obj.var1, obj.var2); // [1,99,1], [1,10,1] —— 独立!
obj.var1 = [...obj.var2]; // ✅ 再次安全恢复
console.log("Restored:", obj.var1, obj.var2); // [1,10,1], [1,10,1]⚠️ 注意事项:
- 若数组包含嵌套对象或深层结构(如 [[1,2], {a:3}]),浅拷贝仅复制第一层引用,内部嵌套仍共享。此时需使用深拷贝(deep copy),如 JSON.parse(JSON.stringify(arr))(适用于纯数据)、结构克隆(structuredClone,现代浏览器支持)或第三方库(Lodash 的 _.cloneDeep)。
- Object.assign({}, obj) 或扩展运算符 {...obj} 仅对对象浅拷贝,不适用于数组;数组必须使用上述数组专用方法。
- 全局作用域中的对象/数组同样遵循引用规则——“全局”不改变其引用语义,仅影响变量生命周期。
总结:JavaScript 中“复制数组”绝非 = 可胜任;理解引用本质是规避隐蔽 bug 的关键。优先使用 [...arr] 实现轻量、可靠的一维数组隔离;面对复杂数据结构,则按需升级至深拷贝策略。










