JavaScript的concat方法怎么合并数组?和扩展运算符有什么区别?
在JavaScript开发中,合并数组是一个非常常见的操作。目前主流的合并方式有两种:传统的 concat() 方法和ES6引入的扩展运算符(...)。它们都能实现合并数组的目的,且都不会修改原数组,而是返回一个新数组,但在语法、灵活性和底层细节上存在一些区别。
一、使用 concat() 方法合并数组
concat() 是数组的一个内置方法,用于合并两个或多个数组。该方法会将参数中的数组元素依次添加到调用者数组的末尾。
1. 基础用法:
const arr1 = [1, 2]; const arr2 = [3, 4]; const mergedArr = arr1.concat(arr2); console.log(mergedArr); // 输出: [1, 2, 3, 4] console.log(arr1); // 输出: [1, 2] (原数组未被修改)
2. 合并多个数组:
const arr1 = [1]; const arr2 = [2]; const arr3 = [3]; const mergedArr = arr1.concat(arr2, arr3); console.log(mergedArr); // 输出: [1, 2, 3]
3. 在合并时插入普通元素:
const arr1 = [1, 2]; // concat不仅可以接受数组,还可以接受普通值 const mergedArr = arr1.concat(3, 4); console.log(mergedArr); // 输出: [1, 2, 3, 4]
二、使用扩展运算符(...)合并数组
扩展运算符是ES6引入的语法,它相当于将数组中的元素“展开”成一个个独立的值。合并数组时,通常配合数组字面量 [] 使用。
1. 基础用法:
const arr1 = [1, 2]; const arr2 = [3, 4]; const mergedArr = [...arr1, ...arr2]; console.log(mergedArr); // 输出: [1, 2, 3, 4]
2. 合并多个数组与灵活插入元素:
const arr1 = [1]; const arr2 = [2]; const arr3 = [3]; // 扩展运算符可以在任意位置插入新元素或其他数组 const mergedArr = [...arr1, 1.5, ...arr2, 2.5, ...arr3]; console.log(mergedArr); // 输出: [1, 1.5, 2, 2.5, 3]
三、concat 与扩展运算符的核心区别
1. 语法的灵活性与直观性
concat 是方法调用,扩展运算符是语法结构。如果在合并时需要在特定位置穿插其他元素,扩展运算符的写法更加直观和自由。而 concat 只能将元素追加在调用者数组的末尾,或者通过多次调用实现,代码较为冗长。
2. 处理嵌套数组(浅拷贝特性一致)
无论是 concat 还是扩展运算符,对原数组都是浅拷贝。如果数组中包含了引用类型(如对象或嵌套数组),合并后的新数组中对应的引用仍然指向原内存地址。修改嵌套对象时,新旧数组都会受到影响。
const arr1 = [{ a: 1 }];
const arr2 = [2];
const mergedConcat = arr1.concat(arr2);
const mergedSpread = [...arr1, ...arr2];
// 修改原数组中的对象
arr1[0].a = 100;
console.log(mergedConcat[0].a); // 输出: 100
console.log(mergedSpread[0].a); // 输出: 1003. 性能差异
在处理极大规模的数组(如十万级以上数据)时,concat() 的性能通常会优于扩展运算符。原因是 concat 是引擎专门为数组操作优化的底层方法,引擎在内部可以预知并一次性分配足够的内存;而扩展运算符在语言规范上是通过迭代器(Iterator)来实现的,引擎需要额外的开销来处理迭代协议。但在日常的普通业务开发中,这种性能差异微乎其微,可以忽略不计。
4. 适用范围(可迭代对象)
扩展运算符不仅可以作用于数组,还可以作用于任何实现了迭代器接口的可迭代对象(如 Set、Map、字符串等)。而 concat 只能用于数组。如果要把一个 Set 转为数组,扩展运算符非常方便,concat 则无法直接做到。
const mySet = new Set([1, 2, 3]); // 扩展运算符可以直接将 Set 转为数组 const arrFromSet = [...mySet]; // [1, 2, 3] // concat 无法直接合并 Set,结果会变成把 Set 对象本身作为一个元素放入数组 const failArr = [].concat(mySet); // [Set(3)]
5. 处理非数组参数的行为差异
concat 在遇到非数组参数时,会直接将其作为一个整体元素插入;而扩展运算符如果直接作用于不可迭代对象(如普通对象或数字),则会直接抛出语法错误。
// concat 直接追加值 const c1 = [1].concat(2, 3); console.log(c1); // [1, 2, 3] // 扩展运算符在数组字面量中追加值 const s1 = [1, ...[2], 3]; console.log(s1); // [1, 2, 3] // 错误示范:扩展运算符不能展开数字 // const s2 = [1, ...2]; // TypeError: 2 is not iterable
四、总结
日常开发推荐: 如果只是简单的数组合并,或者需要在合并时灵活穿插其他元素,扩展运算符语法更简洁、可读性更强,是现代JavaScript的首选。
性能优先场景: 如果涉及海量数据的超大数组合并,推荐使用 concat(),以获得更优的执行效率和内存分配表现。
非数组对象转换: 如果需要合并类数组或 Set/Map 等可迭代对象,必须使用 扩展运算符,或配合
Array.from()使用。