在 JavaScript 中,数组是 引用类型。如果直接赋值,会导致两个变量指向同一个数组,修改其中一个会影响另一个。

const arr1 = [1, 2, 3];
const arr2 = arr1; // 只是引用
arr2[0] = 100;

console.log(arr1); // [100, 2, 3] 也被修改了

为了方便后续翻阅,所以这篇文章整理一下 数组复制 相关概念,并区分:

  • 浅拷贝(Shallow Copy):只复制第一层,内部对象仍是引用。
  • 深拷贝(Deep Copy):完全复制,包括内部对象。

一、浅拷贝(Shallow Copy)

浅拷贝适用于 数组元素为基本类型(数字、字符串、布尔值等)的情况。如果数组里有对象,复制的只是对象的引用,修改副本会影响原数组。

常见方法

1. slice()

slice() 方法会返回一个新数组,其中包含从原始数组中选取的元素。不带参数时,它会复制整个数组。

const arr = [1, 2, 3];
const copy = arr.slice();
2. concat()

concat() 方法用于合并两个或多个数组。通过将一个空数组与目标数组合并,可以实现浅拷贝。

const arr = [1, 2, 3];
const copy = [].concat(arr);
3. 展开运算符 ...
const arr = [1, 2, 3];
const copy = [...arr];
4. Array.from()

此方法从一个类似数组或可迭代对象中创建一个新的、浅拷贝的数组实例。

const arr = [1, 2, 3];
const copy = Array.from(arr);

示例:浅拷贝对对象无效

const arr = [{ a: 1 }, { b: 2 }];
const copy = [...arr];

copy[0].a = 100;
console.log(arr[0].a); // 100,原数组也被修改!

二、深拷贝(Deep Copy)

深拷贝会复制整个数组,包括里面的对象。修改副本不会影响原数组。

常见方法

1. JSON 方法(简易深拷贝)

这是一种简单的深拷贝方法。它通过将数组转换为 JSON 字符串,然后再解析回新的 JavaScript 对象来工作。

const arr = [{ a: 1 }, { b: 2 }];
const copy = JSON.parse(JSON.stringify(arr));

copy[0].a = 100;
console.log(arr[0].a); // 1

缺点: 此方法无法处理函数、undefined、Symbol 值或循环引用。它只适用于简单、可序列化的 JSON 数据。


2. structuredClone(推荐)

structuredClone() 是现代 JavaScript 中推荐的深拷贝方法。它能处理多种数据类型,包括对象、数组、Map、Set,甚至循环引用。

const arr = [{ a: 1 }, { b: 2 }];
const copy = structuredClone(arr);

copy[0].a = 100;
console.log(arr[0].a); // 1
  • 优点:支持对象、数组、MapSet、循环引用等。
  • 需要现代浏览器或 Node.js 17+。

三、方法对比

方法 类型 支持度 适用场景
slice() / concat() 浅拷贝 全支持 简单复制(针对基本类型)
展开运算符 ... 浅拷贝 ES6+ 写法简洁
Array.from() 浅拷贝 ES6+ 转换类数组对象或可迭代对象
JSON.parse(JSON.stringify()) 深拷贝(有限制) 全支持 适合 JSON 数据
structuredClone() 深拷贝 现代环境 推荐,最强

四、总结

  • 浅拷贝:只复制数组的第一层。它性能更好,适用于只包含基本数据类型的数组。
  • 深拷贝:会创建一个完全独立的副本,包括所有嵌套对象。当你处理复杂、嵌套的数据并需要确保副本与原数组完全隔离时,应使用深拷贝。。

开发中,优先用 浅拷贝,性能更好;如果确实需要完全独立的数据,才考虑 深拷贝

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐