文章目录
- 前言
- 一、语法对比
- 1. `Array.prototype.concat()`
- 2. 扩展运算符(解构赋值)
- 二、性能差异(大规模数组)
- 关键差异原因
- 三、适用场景建议
- 总结
前言
最近工作中遇到了一个大规模数组合并相关的问题,在数据合并时有些耗时严重,这里记录一下,这里探究一下concat()
和扩展运算符的差异。
一、语法对比
1. Array.prototype.concat()
直接创建一个新数组,按顺序复制所有元素。内存分配是单次连续操作,引擎可一次性预分配内存。
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = arr1.concat(arr2); // [1, 2, 3, 4, 5, 6]
2. 扩展运算符(解构赋值)
需要多次动态扩容:初始为空数组,逐步添加元素时可能触发多次内存重分配(类似 push())。
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// 扩展运算符执行类似于以下:
// const merged = [];
// for (const item of arr1) merged.push(item);
// for (const item of arr2) merged.push(item);
二、性能差异(大规模数组)
指标 | concat() | 解构赋值 [...arr] |
---|---|---|
时间复杂度 | O(n)(单次连续复制) | O(n)(但含多次扩容开销) |
实际速度 | 更快(引擎高度优化) | 较慢(尤其数组极大时) |
内存峰值 | 较低(预分配连续内存) | 较高(扩容时旧新数组同时存在) |
10 万元素耗时示例 | ~5ms | ~15ms(慢 2-3 倍) |
100 万元素耗时示例 | ~50ms | ~200ms(慢 4 倍以上) |
关键差异原因
-
扩容成本:
解构赋值的动态push()
行为在数组极大时可能触发多次内存扩容(如容量 2→4→8→16…),每次扩容需复制旧数据到新内存区域。 -
引擎优化:
concat()
被 JavaScript 引擎(如 V8)深度优化,可直接操作内存块,避免中间步骤。 -
临时迭代器:
解构赋值需要为每个数组创建迭代器对象,增加额外开销。
三、适用场景建议
场景 | 推荐方法 | 原因 |
---|---|---|
数组合并(> 10,000 元素) | concat() | 性能优势显著,内存占用低 |
小型数组(< 1000 元素) | 解构赋值 | 代码简洁,差异可忽略 |
需动态插入元素 | 解构赋值 | 方便添加额外元素([...a, x, ...b] ) |
内存敏感环境(如低端设备) | concat() | 避免多次扩容导致的内存峰值 |
总结
-
大型数组(> 10k 元素):优先用 concat()(不修改原数组)或 push(…arr)(可修改原数组)。
-
解构赋值 […arr1, …arr2]:仅推荐小型数组或需要代码简洁的场景。
-
性能排序(大数组合并):
push(…arr) > concat() > […arr1, …arr2]