在JavaScript中串联数组的方法

279 阅读6分钟

将多个数组串联成一个数组是一项常见的任务。在JavaScript中,我们可以采取几种不同的方法。其中一些方法会突变目标数组;另一些方法则是不改变所有输入数组,而是返回一个新数组。

在这篇文章中,我想比较以下几种常见的方法。

  • 将元素添加到一个现有的数组中Array.prototype.push()
  • 将元素追加到一个新的数组中Array.prototype.push()
  • 将多个数组串联起来Array.prototype.concat()
  • 在数组字面中使用传播语法

让我们来看看。

向现有数组中添加元素Array.prototype.push()

首先是古老的 Array.prototype.push()方法。让我们假设我们有以下两个数组。

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];

我们可以通过在array2 上循环并重复调用array1.push() ,将array2 的所有元素追加到array1

for (const element of array2) {
  array1.push(element);
}

一旦该代码运行,array1 现在包含所有六个值;它已经被修改到位。array2另一方面,",保持不变。

array1; // [1, 2, 3, 4, 5, 6]
array2; // [4, 5, 6]

取代for...of 循环,我们可以用传播语法array2 的所有元素作为参数传递给push() 的方法调用。

array1.push(...array2);

这等同于下面的方法调用。

array1.push(4, 5, 6);

结果在所有情况下都是一样的。array1 现在包含所有六个值,array2 保持不变。

array1; // [1, 2, 3, 4, 5, 6]
array2; // [4, 5, 6]

有时,突变目标数组可能不是我们想要的行为。当你以函数式的方式写代码时,这一点尤其重要,因为你要组成没有副作用的纯函数。这些函数不应该修改它们的任何参数;因此,你不应该在一个作为参数传递给函数的数组上调用push() 方法。

将元素添加到一个新的数组中Array.prototype.push()

让我们看一下使用push() 方法的方法,该方法没有改变我们要连接的任何数组。这里又是我们的两个输入数组。

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];

我们可以创建一个新的空数组,然后将array1array2 的元素推入其中,而不是将array2 的元素追加到array1

const concatenated = [];
concatenated.push(...array1);
concatenated.push(...array2);

下面是上述代码执行完毕后三个数组的样子。

array1; // [1, 2, 3]
array2; // [4, 5, 6]
concatenated; // [1, 2, 3, 4, 5, 6]

push() 仍然是一个变异方法,但是在这种情况下,它只变异了concatenated ,而让array1array2 保持不变。这种方法甚至在一个以array1array2 为参数的纯函数中也是可以的。只要该函数在给定相同的参数时返回相同的值,并且没有任何副作用(例如修改其参数),它仍然被认为是一个纯函数,即使我们在函数体中局部使用突变。

将多个数组连接起来,并使用Array.prototype.concat()

现在我们已经看到了如何使用 Array.prototype.push()方法,该方法会改变目标数组,让我们看看 Array.prototype.concat()一个非突变的方法。我们将再次从同样的两个数组开始。

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];

然后我们将在array1 上调用concat() 方法,并将array2 作为参数传递。

const concatenated = array1.concat(array2);

由于concat() 方法是非突变的,它既不修改array1 ,也不修改array2 。相反,它返回一个新的数组,其中包含array1array2 的所有元素,并连接在一起。

array1; // [1, 2, 3]
array2; // [4, 5, 6]
concatenated; // [1, 2, 3, 4, 5, 6]

就像push() 方法一样,concat() 方法接受任意多的参数。如果你想把三个或更多的数组串联起来,这很有用。

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const array3 = [7, 8, 9];
const concatenated = array1.concat(array2, array3);

而且就像以前一样,所有的输入数组都保持不变。

array1; // [1, 2, 3]
array2; // [4, 5, 6]
array3; // [7, 8, 9]
concatenated; // [1, 2, 3, 4, 5, 6, 7, 8, 9]

有时,你可能不知道你要串联多少个数组。比方说,我们有一个数组,我们想把它串联成一个数组。

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const array3 = [7, 8, 9];
const arrays = [array1, array2, array3];

再次使用传播语法,我们可以将arrays 的所有元素作为参数传播到concat() 方法调用中。

const concatenated = [].concat(...arrays);

注意,我们在这里创建了一个空数组,这样我们就可以对它调用concat() 方法。因为它不包含任何元素,所以空数组并不改变所产生的连接数组。和以前一样,所有的输入数组保持不变。

array1; // [1, 2, 3]
array2; // [4, 5, 6]
array3; // [7, 8, 9]
arrays; // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
concatenated; // [1, 2, 3, 4, 5, 6, 7, 8, 9]

请注意,concat() 方法并没有递归地平铺数组。它连接所有数组中的所有元素,而不解除嵌套数组的包装。

const array1 = [1, [2], 3];
const array2 = [4, [5, [6]]];
const concatenated = array1.concat(array2);

由此产生的concatenated 数组包含array1 的三个元素,然后是array2 的两个元素,总共有五个元素。

concatenated; // [1, [2], 3, 4, [5, [6]]]
concatenated.length; // 5

在一个数组字面中使用扩展语法

最后,让我们来看看数组字头中的扩展语法。就像以前一样,我们假设有两个输入数组,我们想把它们连接起来。

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];

使用数组字面的传播语法,我们可以创建一个新的数组,其中包含array1 的所有元素,然后是array2 的所有元素。

const concatenated = [...array1, ...array2];

再一次,我们可以看到,array1array2 都没有被修改。

array1; // [1, 2, 3]
array2; // [4, 5, 6]
concatenated; // [1, 2, 3, 4, 5, 6]

传播语法的好处是,它调用了我们正在传播的元素的迭代协议。这意味着传播适用于任何可迭代的元素,而不是只适用于数组。例如,我们可以将一个数组中的所有值 Set中的所有值传播到一个新的数组中。

const uniques = new Set([1, 2, 2, 3, 3, 3]);
const array = [...uniques];

uniques; // Set (3) {1, 2, 3}
array; // [1, 2, 3]

当你想把多个数组串联成一个数组并删除任何重复的值时,这很有用。

const array1 = [1, 2, 3];
const array2 = [2, 3, 4];
const uniques = [...new Set([...array1, ...array2])];

我们将array1array2 串联成一个新的数组,其中包含所有六个元素:[1, 2, 3, 2, 3, 4] 。这个新数组被传递给Set 构造函数。集合不能包含重复的值,所以当我们将集合分散到外部的新数组中时,我们最终会得到四个唯一的值。

array1; // [1, 2, 3]
array2; // [2, 3, 4]
uniques; // [1, 2, 3, 4]

Summary

我们已经看到了将多个数组串联成一个数组的不同方法。

  • 使用Array.prototype.push() 方法
  • 使用Array.prototype.concat() 方法
  • 在数组字面中使用蔓延语法

最重要的是,你应该记住,push() 会突变目标数组,在原地修改它。另一方面,concat() 方法和数组字词中的扩散语法是不改变的;这两种方法都是创建一个新的数组。