Both Function.prototype.apply and the spread syntax may cause a stack overflow when applied to large arrays:
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)
Use Array.prototype.concat instead. Besides avoiding stack overflows concat has the advantage that it also avoids mutations. Mutations are considered harmful, because they can lead to subtle side effects.
But that isn’t a dogma. If you are wihtin a function scope and perform mutations to improve performance and relieve garbage collection you can perform mutations, as long as they aren’t visible in the parent scope.