如何扩展现有的JavaScript数组与另一个数组,而不创build一个新的数组?

注意:不是如何将一些东西添加到数组的副本? – 这里的目标是将一个数组的全部内容添加到另一个数组中,并且“就地”这样做,即不拷贝扩展数组的所有元素。

似乎没有办法用另一个数组扩展现有的JavaScript数组,也就是模拟Python的extend方法。

我想达到的是以下几点:

 >>> a = [1, 2] [1, 2] >>> b = [3, 4, 5] [3, 4, 5] >>> SOMETHING HERE >>> a [1, 2, 3, 4, 5] 

我知道有一个a.concat(b)方法,但它创build一个新的数组,而不是简单地扩展第一个。 我想要一个algorithm,当a明显大于b (即不复制a的algorithm)高效工作。

.push方法可以接受多个参数,所以通过使用.apply将第二个数组的所有元素作为parameter passing给.push ,你可以得到你想要的结果:

 >>> a.push.apply(a, b) 

或者,如果你认为它更清楚:

 >>> Array.prototype.push.apply(a,b) 

你应该使用基于循环的技术。 本页上的其他答案基于使用.apply可能会失败的大型数组。

一个相当简洁的基于循环的实现是:

 Array.prototype.extend = function (other_array) { /* you should include a test to check whether other_array really is an array */ other_array.forEach(function(v) {this.push(v)}, this); } 

然后您可以执行以下操作:

 var a = [1,2,3]; var b = [5,4,3]; a.extend(b); 

DzinX的答案 (使用push.apply)和其他基于.apply的方法失败,当我们追加的数组很大(testing表明,对于我来说,在Chrome中大约150000个条目,在Firefox中大于500000个条目)。 你可以看到这个错误发生在这个jsperf 。

发生错误的原因是当调用“Function.prototype.apply”作为第二个参数的大数组时调用堆栈大小超出。 (MDN使用Function.prototype.apply注意了超出调用堆栈大小的危险 – 请参阅“应用和内置函数”一节)

为了与本页其他答案进行速度比较,请查看此jsperf (感谢EaterOfCode)。 基于循环的实现在速度上与使用Array.push.apply相似,但往往比Array.slice.apply慢一点。

有趣的是,如果你正在追加的数组是稀疏的,上面的forEach方法可以利用稀疏性并且胜过基于.apply的方法,如果你想自己testing这个,请查看这个jsperf 。

顺便说一句,不要被诱惑(像我一样!),以进一步缩短forEach实现:

 Array.prototype.extend = function (array) { array.forEach(this.push, this); } 

因为这会产生垃圾结果! 为什么? 因为Array.prototype.forEach为它调用的函数提供了3个参数 – 它们是:(element_value,element_index,source_array)。 如果你使用“forEach(this.push,this)”,所有这些将被推到你的第一个数组forEach(每forEach迭代)!

对于那些简单地search“JavaScript数组扩展”,并在这里,你可以很好地使用Array.concat

 var a = [1, 2, 3]; a = a.concat([5, 4, 3]); 

Concat将返回一个新的数组,作为线程启动器不想要的。 但是你可能不在乎(当然对于大多数用途来说,这将是好的)。


这里也有一些很好的ES6糖,它们以扩散算子的forms出现:

 const a = [1, 2, 3]; const b = [...a, 5, 4, 3]; 

(也复制)

我觉得这些天最优雅的是:

 arr1.push(...arr2); 

关于传播运算符的MDN文章在ES2015(ES6)中提到了这个很好的含义:

更好的推动

示例:push通常用于将数组推到现有数组的末尾。 在ES5中,这通常是这样做的:

 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Append all items from arr2 onto arr1 Array.prototype.push.apply(arr1, arr2); 

在传播的ES6中变成:

 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1.push(...arr2); 

请注意, arr2不能很大(保持在100 000左右),因为调用堆栈溢出,根据jcdude的答案。

如果你想使用jQuery,有$ .merge()

例:

 a = [1, 2]; b = [3, 4, 5]; $.merge(a,b); 

结果:a = [1, 2, 3, 4, 5]

首先关于JavaScript中的apply(),了解我们为什么使用apply:

apply()方法使用给定的这个值调用一个函数,并以一个数组的forms提供参数。

你可以使用apply将第一个数组轻松地推送到另一个数组中。 根据第一行应用接受数组作为参数,所以你基本上只推送值。
想象一下你有这些数组:

 var a = [1, 2, 3, 4]; var b = [5, 6, 7]; 

只要这样做:

 Array.prototype.push.apply(a, b); 

结果是:

 a = [1, 2, 3, 4, 5, 6, 7]; 

同样的东西在ES6中,可以使用…操作符来完成:

 a.push(...b); //a = [1, 2, 3, 4, 5, 6, 7]; 

目前所有的浏览器都更短,更好,但并不完全支持。

另外,如果你基本上想要将数组bb移动到a并且使数组b同时为空,那么可以这样做。

 while(b.length) { a.push(b.shift()); } 

结果如下:

 a = [1, 2, 3, 4, 5, 6, 7]; b = []; 

我喜欢上面描述的a.push.apply(a, b)方法,如果你想要,你总是可以像这样创build一个库函数:

 Array.prototype.append = function(array) { this.push.apply(this, array) } 

像这样使用它

 a = [1,2] b = [3,4] a.append(b) 

使用splice()可以做到这一点:

 b.unshift(b.length) b.unshift(a.length) Array.prototype.splice.apply(a,b) b.shift() // restore b b.shift() // 

但是尽pipe更push.apply ,它并不比push.apply快,至less在Firefox 3.0中不是。 为完整起见。

您可以创build一个polyfill来扩展,如下所示。 它将添加到数组中; 就地并自行返回,以便您可以链接其他方法。

 if (Array.prototype.extend === undefined) { Array.prototype.extend = function(other) { this.push.apply(this, arguments.length > 1 ? arguments : other); return this; }; } function print() { document.body.innerHTML += [].map.call(arguments, function(item) { return typeof item === 'object' ? JSON.stringify(item) : item; }).join(' ') + '\n'; } document.body.innerHTML = ''; var a = [1, 2, 3]; var b = [4, 5, 6]; print('Concat'); print('(1)', a.concat(b)); print('(2)', a.concat(b)); print('(3)', a.concat(4, 5, 6)); print('\nExtend'); print('(1)', a.extend(b)); print('(2)', a.extend(b)); print('(3)', a.extend(4, 5, 6)); 
 body { font-family: monospace; white-space: pre; } 

我可以看到非常好的答案,并且全部取决于您的arrays大小,您的要求和目标。 它可以做不同的方式。

我build议使用JavaScript For Loop:

 var a = [1, 2]; var b = [3, 4, 5]; for (i = 0; i < b.length; i++) { a.push(b[i]); } 

console.log(a)输出将是

 Array [ 1, 2, 3, 4, 5 ] 

那么你可以做你自己的function:

 function extendArray(a, b){ for (i = 0; i < b.length; i++) { a.push(b[i]); } return a; } 

console.log(extendArray(a, b)); 输出将是

 Array [ 1, 2, 3, 4, 5 ] 

结合答案…

 Array.prototype.extend = function(array) { if (array.length < 150000) { this.push.apply(this, array) } else { for (var i = 0, len = array.length; i < len; ++i) { this.push(array[i]); }; } } 

另一种解决scheme来合并两个以上的数组

 var a = [1, 2], b = [3, 4, 5], c = [6, 7]; // Merge the contents of multiple arrays together into the first array var mergeArrays = function() { var i, len = arguments.length; if (len > 1) { for (i = 1; i < len; i++) { arguments[0].push.apply(arguments[0], arguments[i]); } } }; 

然后调用并打印为:

 mergeArrays(a, b, c); console.log(a) 

输出将是: Array [1, 2, 3, 4, 5, 6, 7]

答案非常简单。

 >>> a = [1, 2] [1, 2] >>> b = [3, 4, 5] [3, 4, 5] >>> SOMETHING HERE (the following code will combine the 2 arrays) a = a.concat(b); >>> a [1, 2, 3, 4, 5] 

Concat的行为非常类似于JavaScriptstring连接。 它将返回你放入concat函数的参数的组合,在你调用该函数的数组的末尾。 关键是你必须把返回的值赋值给一个variables,否则就会丢失。 所以例如

 a.concat(b); <---This does absolutely nothing since it is just returning the combined arrays but it doesn't do anything with it