Net*_*yth 21 javascript arrays apply ecmascript-6 spread-syntax
我有两个数组,
const pets = ["dog", "cat", "hamster"]
const wishlist = ["bird", "snake"]
Run Code Online (Sandbox Code Playgroud)
我要附加wishlist到pets,可以使用两种方法来完成,
方法1:
pets.push.apply(pets,wishlist)
Run Code Online (Sandbox Code Playgroud)
结果如下: [ 'dog', 'cat', 'hamster', 'bird', 'snake' ]
方法2:
pets.push(...wishlist)
Run Code Online (Sandbox Code Playgroud)
这也导致: [ 'dog', 'cat', 'hamster', 'bird', 'snake' ]
当我处理更大的数据时,这两种方法在性能方面是否存在差异?
小智 19
Function.prototype.apply当应用于大型数组时,两者和扩展语法都可能导致堆栈溢出:
let xs = new Array(500000),
ys = [], zs;
xs.fill("foo");
try {
ys.push.apply(ys, xs);
} catch (e) {
console.log("apply:", e.message)
}
try {
ys.push(...xs);
} catch (e) {
console.log("spread:", e.message)
}
zs = ys.concat(xs);
console.log("concat:", zs.length)Run Code Online (Sandbox Code Playgroud)
请Array.prototype.concat改用.除了避免堆栈溢出之外concat,还具有避免突变的优点.突变被认为是有害的,因为它们可能导致微妙的副作用.
但这不是教条.如果您正在使用函数作用域并执行突变以提高性能并减少垃圾回收,则可以执行突变,只要它们在父作用域中不可见即可.
对于附加到大型数组,扩展运算符要快得多。我不知道他们@ftor是如何@Liau Jian Jie得出结论的,可能是糟糕的测试。
Chrome 71.0.3578.80 (Official Build) (64-bit), FF 63.0.3 (64-bit), &Edge 42.17134.1.0
这是有道理的,因为concat()创建了数组的副本,甚至不尝试使用相同的内存。
关于“突变”的事情似乎没有任何根据;如果您覆盖旧数组,concat()则没有任何好处。
不使用的唯一原因...是堆栈溢出,我同意您不能使用...或的apply其他答案。
但即便如此,仅使用 a 的速度for {push()}或多或少是所有浏览器中的两倍concat(),并且不会溢出。除非您需要保留旧数组,
否则
没有理由使用。concat()
通过推送,您可以追加到现有数组,通过扩展运算符,您可以创建一个副本。
a=[1,2,3]
b=a
a=[...a, 4]
alert(b);
Run Code Online (Sandbox Code Playgroud)
=> 1, 2, 3
a=[1,2,3]
b=a
a.push(4)
alert(b);
Run Code Online (Sandbox Code Playgroud)
=> 1, 2, 3, 4
也推.应用:
a=[1,2,3]
c=[4]
b=a
Array.prototype.push.apply(a,c)
alert(b);
Run Code Online (Sandbox Code Playgroud)
=> 1, 2, 3, 4
concat 是一个副本
a=[1,2,3]
c=[4]
b=a
a=a.concat(c)
alert(b);
Run Code Online (Sandbox Code Playgroud)
=> 1, 2, 3
优选通过引用,特别是对于较大的阵列。
扩展运算符是一种快速进行复制的方法,传统上是通过以下方式完成的:
a=[1,2,3]
b=[]
a.forEach(i=>b.push(i))
a.push(4)
alert(b);
Run Code Online (Sandbox Code Playgroud)
=> 1, 2, 3
如果您需要副本,请使用扩展运算符,速度很快。或者使用 @ftor 指出的 concat。如果没有,请使用推送。但请记住,在某些情况下您无法进行变异。此外,使用这些函数中的任何一个,您都将获得浅拷贝,而不是深拷贝。对于深度复制,您将需要 lodash。在这里阅读更多信息: https: //slemgrim.com/mutate-or-not-to-mutate/