concat() 更适合中大型数组合并,因其一次性内存分配、无栈溢出风险、支持多参数且兼容性好;展开运算符简洁但小数组适用,大数组易致性能下降。

要合并数组,concat() 和展开运算符([...arr1, ...arr2])都能创建新数组,但它们的底层行为、适用场景和性能表现差异明显。选错方法在小数据时无感,一到中大型数组就容易拖慢响应、触发栈溢出或加重内存压力。
concat() 的特点与适用场景
concat() 是原生数组方法,语义明确、兼容性好,不修改原数组,返回一个全新数组。
- 内存分配是一次性的:引擎可预估总长度并连续分配,避免反复扩容
- 不会触发最大参数限制:无论数组多长,都不会报
RangeError: Maximum call stack size exceeded - 适合中大型数组(1000+ 元素),尤其是生产环境或需保持不可变性的场景(如 React 状态更新、Redux)
- 支持多个参数:
arr1.concat(arr2, arr3, arr4)直接合并多个,比链式调用更干净
展开运算符的优缺点
展开运算符写法简洁,可读性强,但本质是“语法糖”,实际执行类似多次 push()。
- 小数组(concat(),代码更直观
- 大数组时可能多次触发内部数组扩容,时间复杂度仍是 O(n),但内存分配更碎片化
- 当单个数组超过约 65,536 个元素时,
[...arr]会因参数数量超限而失败 - 无法中断遍历,也不支持惰性求值,对超大数据集不够友好
性能关键点对比
实测表明:
- 合并两个 10 万级基本类型数组:
concat()通常比展开快 10%–20%,且内存更稳定 - 合并对象数组时,两者性能差距缩小,但展开仍更容易引发 GC 压力
- 若需合并 3 个以上数组,
concat(a, b, c, d)比[...a, ...b, ...c, ...d]更安全、更可控 - 在热路径(如动画帧、高频事件)中,应优先用
concat()或直接循环push(),避开展开
什么时候该换方法?
不必死守某一种写法,按需切换更实际:
- 要原地追加?用
target.push(...source)或循环for (const x of source) target.push(x) - 要零拷贝或极致性能?小规模可考虑
Uint8Array或TypedArray.set() - 要合并后去重?别拼
concat+Set,直接用[...new Set([...a, ...b])]或Array.from(new Set(a.concat(b))) - 处理超大数组(百万级)?前端合并可能已不是最优解,应考虑分片、流式处理或后端聚合










