JavaScript 中数组赋值与展开运算符浅拷贝的本质区别

1次阅读

JavaScript 中数组赋值与展开运算符浅拷贝的本质区别

本文详解 const arr2 = arr1(引用赋值)与 const arr2 = […arr1](浅拷贝)的核心差异,通过代码实证说明二者在内存指向、修改影响及嵌套结构行为上的根本不同。

本文详解 `const arr2 = arr1`(引用赋值)与 `const arr2 = […arr1]`(浅拷贝)的核心差异,通过代码实证说明二者在内存指向、修改影响及嵌套结构行为上的根本不同。

javaScript 中,将一个数组赋值给另一个变量时,看似相似的两行代码却蕴含截然不同的语义和运行时行为:

const arr1 = [1, 2, 3, 4, 5];  const arr2 = [...arr1]; // ✅ 创建新数组:浅拷贝 const arr3 = arr1;       // ⚠️ 复用原引用:指向同一内存地址

关键区别在于:前者生成一个独立的新数组实例,后者仅复制引用(即两个变量指向内存中的同一个数组对象)。

? 行为对比:一改全改 vs 互不影响

可通过严格相等(===)和元素修改来直观验证:

const arr = [1, 2, 3];  const arrA = [...arr]; // 浅拷贝 → 新数组 const arrB = arr;       // 引用赋值 → 同一数组  console.log(arr === arrA); // false(不同对象) console.log(arr === arrB); // true  (同一对象)  // 修改 arrA 不影响 arr arrA[0] = 9; console.log(arr);  // [1, 2, 3] console.log(arrA); // [9, 2, 3]  // 修改 arrB 等同于修改 arr arrB[0] = 9; console.log(arr);  // [9, 2, 3] console.log(arrB); // [9, 2, 3]

结论一:若需隔离操作、避免副作用(如函数内修改不应影响原始数据),必须使用 […arr] 或其他浅拷贝方式(如 arr.slice()、Array.from(arr)、structuredClone()(深拷贝,ES2022+))。

立即学习Java免费学习笔记(深入)”;

⚠️ 注意:浅拷贝 ≠ 深拷贝

展开运算符 … 实现的是浅拷贝——它仅复制数组第一层元素的值(对基本类型)或引用(对对象/嵌套数组)。深层嵌套结构仍共享引用:

const arr = [1, 2, [5, 6]];  const arrA = [...arr]; const arrB = arr;  // 修改顶层元素:互不影响 arrA[0] = 8;      // arr 保持 [1, 2, [5, 6]] console.log(arr[0]); // 1  // 修改嵌套数组内部:仍会联动! arrA[2][0] = 9; console.log(arr[2][0]); // 9 ← 被意外修改! console.log(arr);       // [1, 2, [9, 6]] console.log(arrA);      // [8, 2, [9, 6]]

这说明:[…arr] 对嵌套数组、对象等引用类型,拷贝的是其内存地址,而非递归创建副本。

? 实用建议与替代方案

场景 推荐方式 说明
简单一维数组(仅数字、字符串 […arr]、arr.slice() 性能好、语法简洁
需要真正隔离所有层级(含对象/嵌套数组) structuredClone(arr) 原生深拷贝(现代浏览器 & Node.js ≥17.0),支持 map/Set/date
兼容旧环境 json.parse(JSON.stringify(arr)) 仅适用于可序列化数据(不支持函数、undefinedsymbol循环引用)
函数式编程习惯 始终避免直接修改输入数组,优先返回新数组 如使用 map、Filter、concat 等不可变方法

✅ 总结

  • const arr2 = arr1 是引用赋值:arr2 和 arr1 指向同一数组对象,任何一方修改都会反映到另一方;
  • const arr2 = […arr1] 是浅拷贝:创建新数组,顶层元素独立,但嵌套对象/数组仍共享引用;
  • 判断是否需要拷贝?问自己:“后续是否可能修改 arr2,且不希望影响 arr1?” 若答案为是,就必须拷贝;若需完全隔离深层结构,则需深拷贝。

理解这一区别,是写出可预测、易调试、符合函数式思维的 javascript 数组操作代码的基础。

text=ZqhQzanResources