数码常识网
霓虹主题四 · 更硬核的阅读氛围

数组复制操作:别再直接赋值了,小心坑

发布时间:2025-12-14 07:36:10 阅读:256 次

写代码时经常要处理一堆数据,数组就是最常用的工具之一。有时候我们需要把一个数组的内容搬到另一个变量里去,比如做数据备份、准备计算前的原始记录,或者传给别的函数处理。这时候很多人第一反应是直接赋值:

let arr1 = [1, 2, 3];
let arr2 = arr1;
arr2.push(4);
console.log(arr1); // [1, 2, 3, 4]

咦?我明明是往 arr2 里加的元素,怎么 arr1 也变了?这就是典型的“引用坑”。JavaScript 中数组是引用类型,直接赋值只是把“地址”传过去了,两个变量其实指向同一块内存。改一个,另一个自然跟着变。

真正复制数组的几种方法

要想让新数组独立出来,得做“深一点”的操作。下面这几个方法比较靠谱:

1. 展开运算符(Spread)

这是现在最常用也最简洁的方式:

let arr1 = [1, 2, 3];
let arr2 = [...arr1];
arr2.push(4);
console.log(arr1); // [1, 2, 3]
console.log(arr2); // [1, 2, 3, 4]

这样 arr2 就是一个全新的数组,和 arr1 没有关系了。适合大多数场景,尤其是浅层数据。

2. slice() 方法

这个老方法其实一直很稳:

let arr1 = ['a', 'b', 'c'];
let arr2 = arr1.slice();
arr2.pop();
console.log(arr1); // ['a', 'b', 'c']
console.log(arr2); // ['a', 'b']

slice 不传参数时,默认从头截到尾,相当于复制整个数组。虽然写法不如展开运算符直观,但在一些老项目里还能看到它的身影。

3. concat() 方法

本来是用来拼接数组的,但也可以拿来复制:

let arr1 = [10, 20];
let arr2 = [].concat(arr1);
arr2.push(30);
console.log(arr1); // [10, 20]
console.log(arr2); // [10, 20, 30]

原理是创建一个新数组,然后把原数组拼上去。效果一样,就是写起来稍微绕一点。

注意:深层嵌套还得靠深拷贝

上面这些方法都只能“浅复制”。如果数组里还有对象或嵌套数组,里面的引用还是共用的:

let arr1 = [{ name: '张三' }, { name: '李四' }];
let arr2 = [...arr1];
arr2[0].name = '王五';
console.log(arr1[0].name); // 王五 —— 还是被改了!

这时候就得用深拷贝了。简单粗暴的方法可以用 JSON 转一圈:

let arr2 = JSON.parse(JSON.stringify(arr1));

不过这招有局限,比如处理不了函数、undefined 或 Date 对象。复杂场景建议用 lodash 的 cloneDeep,或者自己递归实现。

日常开发中,多数时候用展开运算符就够了。关键是明白:复制不是默认行为,得主动去做。别让一个小小的赋值,拖垮了整个逻辑。