似乎没有办法用另一个数组来扩展一个现有的JavaScript数组,即模仿Python的extend方法。

我想达到以下几点:

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

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

注意:这不是“如何将内容追加到数组?”这里的目标是将一个数组的全部内容添加到另一个数组中,并做到“就地”,即不复制扩展数组的所有元素。


当前回答

使用数组。extend而不是Array。推送> 150,000条记录。

if (!Array.prototype.extend) {
  Array.prototype.extend = function(arr) {
    if (!Array.isArray(arr)) {
      return this;
    }

    for (let record of arr) {
      this.push(record);
    }

    return this;
  };
}

其他回答

2018年更新:更好的答案是我的一个更新的答案:A .push(…b)。不要再给这个投票了,因为它从来没有真正回答过这个问题,但它是2015年关于谷歌第一次点击的黑客攻击:)


对于那些仅仅搜索“JavaScript数组扩展”并到达这里的人来说,您可以很好地使用array .concat。

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

Concat将返回一个新数组的副本,这是线程启动者不想要的。但您可能并不关心(当然对于大多数用途来说,这是可以的)。


ECMAScript 6中还有一些很好的扩展操作符:

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]; //将arr2中的所有项追加到arr1 Array.prototype.push。应用(arr1 arr2); 在ES6中,这变成: Var arr1 = [0,1,2]; Var arr2 = [3,4,5]; arr1.push(…arr2);

请注意arr2不能太大(保持在大约100,000项以下),因为根据jcdude的回答,调用堆栈会溢出。

只需在push()方法的帮助下向数组添加新元素就可以做到这一点。

let colors = ["Red", "Blue", "Orange"]; console.log(' push前数组:' + colors); //添加新值到数组 colors.push(“绿色”); console.log(' push后数组:' + colors);

另一个用于将元素追加到数组开头的方法是unshift()函数,它添加并返回新的长度。它接受多个参数,附加现有元素的索引,最后返回数组的新长度:

let colors = ["Red", "Blue", "Orange"]; console.log(' unshift前数组:' + colors); //添加新值到数组 颜色。未(“黑色”,“绿色”); console.log(' unshift后的数组:' + colors);

还有其他方法。你可以在这里查看。

您应该使用基于循环的技术。本页上基于.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的方法失败时,我们附加的数组很大(测试表明,对我来说,大是>大约150000个条目在Chrome, > 500000个条目在Firefox)。您可以在这个jsperf中看到这个错误。

当'Function.prototype. size '时,调用堆栈大小超过,因此发生错误。Apply '调用时使用一个大数组作为第二个参数。(MDN有一个关于使用Function.prototype.apply超过调用堆栈大小的危险的说明-请参阅标题为“apply和内置函数”的部分。)

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

有趣的是,如果你要追加的数组是稀疏的,上面基于forEach的方法可以利用稀疏性并优于基于.apply的方法;如果您想亲自测试,请查看这个jsperf。

顺便说一下,不要试图(像我一样!)进一步缩短forEach实现为:

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

因为这会产生垃圾结果!为什么?因为Array.prototype.forEach为它调用的函数提供了三个参数(element_value, element_index, source_array)。如果你使用“forEach(this。推动,这)”!

答案非常简单。

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

a = a.concat(b);

>>> a
[1, 2, 3, 4, 5]

Concat的作用与JavaScript字符串连接非常相似。它将返回您在调用函数的数组末尾放入concat函数的参数的组合。关键是你必须把返回值赋给一个变量,否则它就会丢失。例如,

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