
本文详解 const arr2 = arr1(引用赋值)与 const arr2 = […arr1](浅拷贝赋值)的核心差异,通过代码实证说明二者在内存引用、修改影响及嵌套结构处理上的根本不同。
本文详解 `const arr2 = arr1`(引用赋值)与 `const arr2 = […arr1]`(浅拷贝赋值)的核心差异,通过代码实证说明二者在内存引用、修改影响及嵌套结构处理上的根本不同。
在 javaScript 中,将一个数组赋值给另一个变量时,看似相似的两种写法——const arr2 = arr1 和 const arr2 = […arr1]——实际代表完全不同的内存行为。理解这一区别,是避免意外副作用、编写可预测代码的关键基础。
引用赋值:共享同一内存地址
当执行 const arr2 = arr1 时,javascript 并未创建新数组,而是将 arr1 所指向的数组对象的引用复制给 arr2。这意味着 arr1 和 arr2 指向内存中的同一个数组实例。对任一变量的修改(如 arr2.push(6) 或 arr2[0] = 9),都会直接反映在另一个变量上。
const arr1 = [1, 2, 3]; const arr2 = arr1; // 引用赋值 console.log(arr1 === arr2); // true —— 严格相等,指向同一对象 arr2[0] = 99; console.log(arr1); // [99, 2, 3] —— arr1 同步被修改
展开运算符赋值:创建浅拷贝
而 const arr2 = […arr1] 利用扩展语法(spread syntax)对 arr1 进行浅拷贝(shallow copy):它新建一个数组,并将 arr1 的第一层元素值逐个复制过去。新旧数组在内存中是两个独立对象,互不影响——但仅限于第一层。
const arr1 = [1, 2, 3]; const arr2 = [...arr1]; // 浅拷贝赋值 console.log(arr1 === arr2); // false —— 不同对象 arr2[0] = 99; console.log(arr1); // [1, 2, 3] —— 未受影响 console.log(arr2); // [99, 2, 3]
关键限制:浅拷贝不递归深入嵌套结构
需特别注意,“浅拷贝”仅复制顶层基本类型值(如数字、字符串)和引用类型(如子数组、对象)的引用本身,而非其内部内容。若原数组包含嵌套数组或对象,修改嵌套项仍会导致双方同步变化:
立即学习“Java免费学习笔记(深入)”;
const arr1 = [1, 2, [5, 6]]; const arr2 = [...arr1]; // 浅拷贝:arr2[2] 仍指向 arr1[2] 的同一数组 arr2[2][0] = 9; // 修改嵌套数组的第一个元素 console.log(arr1[2][0]); // 9 —— arr1 也被改变! console.log(arr1[2] === arr2[2]); // true —— 嵌套数组引用未被复制
✅ 何时用哪种方式?
- 使用 arr2 = arr1:当你明确需要两个变量协同操作同一数组(如多个函数共用配置列表且允许相互修改)。
- 使用 […arr1]:当你需要隔离变更、避免污染原始数据(如在函数中临时处理数组、实现不可变更新、React 状态更新等场景)。
- 需深拷贝嵌套结构?请改用 json.parse(JSON.stringify(arr1))(仅限纯数据)、structuredClone()(现代环境推荐)或 Lodash 的 _.cloneDeep()。
⚠️ 注意事项:
- Array.from(arr1)、arr1.slice()、arr1.concat() 等方法也生成浅拷贝,效果等同 […arr1];
- Object.assign([], arr1) 同样是浅拷贝,但语义不如扩展运算符清晰;
- 对于大型数组,浅拷贝存在性能开销,高频操作需权衡;
- 类型检查工具(如 typescript)无法自动识别引用/拷贝差异,逻辑正确性依赖开发者意识。