Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 处理数组时使用扩展语法(…)和push.apply的区别_Javascript_Arrays_Ecmascript 6_Apply_Spread Syntax - Fatal编程技术网

Javascript 处理数组时使用扩展语法(…)和push.apply的区别

Javascript 处理数组时使用扩展语法(…)和push.apply的区别,javascript,arrays,ecmascript-6,apply,spread-syntax,Javascript,Arrays,Ecmascript 6,Apply,Spread Syntax,我有两个数组 const pets = ["dog", "cat", "hamster"] const wishlist = ["bird", "snake"] 我想将wishlist附加到pets,这可以使用两种方法完成 方法1: pets.push.apply(pets,wishlist) 结果是:[‘狗’、‘猫’、‘仓鼠’、‘鸟’、‘蛇’] 方法2: pets.push(...wishlist) 这也导致:[‘狗’、‘猫’、‘仓鼠’、‘鸟’、‘蛇’] 在处理较大数据时,这两种方法在

我有两个数组

const pets = ["dog", "cat", "hamster"]

const wishlist = ["bird", "snake"]
我想将
wishlist
附加到
pets
,这可以使用两种方法完成

方法1:

pets.push.apply(pets,wishlist)
结果是:
[‘狗’、‘猫’、‘仓鼠’、‘鸟’、‘蛇’]

方法2:

pets.push(...wishlist)
这也导致:
[‘狗’、‘猫’、‘仓鼠’、‘鸟’、‘蛇’]


在处理较大数据时,这两种方法在性能方面是否存在差异?

如果您使用的是ES2015,则扩展运算符是一种可行的方法。与其他方法相比,使用spread运算符时,代码看起来不那么冗长,也更干净。说到速度,我相信在这两种方法之间几乎没有什么可选择的。

这两种方法都是Function.prototype.apply,当应用于大型阵列时,扩展语法可能会导致堆栈溢出:

让xs=新阵列(500000),
ys=[],zs;
xs.fill(“foo”);
试一试{
ys.push.apply(ys,xs);
}捕获(e){
log(“apply:,e.message)
}
试一试{
推送(…xs);
}捕获(e){
console.log(“传播:”,e.message)
}
zs=ys.concat(xs);
console.log(“concat:,zs.length)
除了,
Array.prototype.concat
平均比Array spread操作符快至少1.4倍

请参见此处的结果:


您可以在您自己的浏览器和机器上运行测试:

将问题解释为
,通常使用.push()作为示例,
它看起来应用速度[仅略]快一些(MS Edge除外,见下文)

这两种方法的动态调用函数的开销

function test() { console.log(arguments[arguments.length - 1]); }
var using = (new Array(200)).fill(null).map((e, i) => (i));


我在Chrome 71.0.3578.80(官方版本)(64位),
FF 63.0.3(64位)
,&
Edge 42.17134.1.0
中进行了测试,这些都是我自己运行了几次后的结果。最初的结果总是向某个方向倾斜

正如您所看到的,Edge对
apply
的实现似乎比它对
..
的实现更好(但不要尝试在不同浏览器之间比较结果,我们无法从这些数据中判断Edge的
apply
是否比其他浏览器更好,
..
是否更差,或者两者兼而有之)。
有鉴于此,除非您专门针对Edge,否则我会说使用
,就像它读起来更干净一样,特别是如果您需要将对象传递回
应用
以获得

它也可能取决于数组的大小,所以就像
@Jaromanda X
所说的那样,进行您自己的测试并更改
200
,如果您需要真正确定的话



其他答案将该问题解释为
,这对.push()更有利,特别是
,并关注正在解决的“问题”,只是建议
只使用.concat()
,这基本上是标准的
为什么要这样做?
这会让一些来自谷歌的人感到厌烦,因为他们不想用
.push()
(比如说,
Math.max
,或者你自己的自定义函数)来寻找解决方案。我不知道他们的结论是怎么得出的,可能是糟糕的测试

Chrome 71.0.3578.80(官方版本)(64位)
FF 63.0.3(64位)
,&
Edge 42.17134.1.0

这是有意义的,因为
concat()
复制数组,甚至不尝试使用相同的内存

关于“突变”的事情似乎没有任何根据;如果要覆盖旧数组,
concat()
没有任何好处

不使用
..
的唯一原因是堆栈溢出,我同意您不能使用
..
应用的其他答案
但是,即使在所有浏览器中,仅使用
作为{push()}
的速度也差不多是
concat()的两倍,而且不会溢出。

没有理由使用
concat()
,除非需要保留旧数组。

使用push将附加到现有数组,使用spread操作符创建副本

a=[1,2,3]
b=a
a=[...a, 4]
alert(b);
=>1,2,3

 a=[1,2,3]
b=a
a.push(4)
alert(b);
=>1,2,3,4

推送。同时应用:

a=[1,2,3]
c=[4]
b=a
Array.prototype.push.apply(a,c)
alert(b);
=>1,2,3,4

康卡特是复制品

a=[1,2,3]
c=[4]
b=a
a=a.concat(c)
alert(b);
=>1,2,3

 a=[1,2,3]
b=a
a.push(4)
alert(b);
通过引用是最好的,尤其是对于较大的阵列

“Spread operator”是一种快速复制方式,传统上可以通过以下方式进行复制:

a=[1,2,3]
b=[]
a.forEach(i=>b.push(i))
a.push(4)
alert(b);
=>1,2,3

 a=[1,2,3]
b=a
a.push(4)
alert(b);

如果您需要副本,请使用spread操作符,这样做很快。或者使用@ftor指出的concat。如果没有,请使用推送。然而,请记住,有些情况下你不能变异。此外,使用这些函数中的任何一个,您都将获得浅拷贝,而不是深拷贝。对于深度复制,您将需要lodash。阅读更多信息:

用户6445533的答案被接受为答案,但我觉得测试用例有点奇怪。这似乎不是通常应该如何使用扩展运算符

为什么不能像这样做:

let newPets = [...pets, ...wishlist]
它不会面临上述任何stackoverflow问题。 正如Hashbrown所提到的,它也可能给您带来性能上的好处


<>我也在学习ES6。对不起,如果我错了

定义“更大”的数据-firefox使用方法2看起来更慢。。。其他浏览器可能会更快。。。尝试您自己的基准测试如果您正在转换到ES5,Babel/TypeScript等很有可能会生成与pets.push.apply完全相同的代码。在任何情况下,性能差异影响应用程序速度的可能性都很小。为什么你会奇怪呢?在JS中,你可以向一个函数发送不确定数量的参数,但不能发送不确定数量的参数。根据当前会话可用堆栈大小,有一个限制