spread operator vs array.concat()

时间:2018-02-19 11:57:24

标签: javascript arrays angular typescript operators

spread operatorarray.concat()

之间有何区别?



let parts = ['four', 'five'];
let numbers = ['one', 'two', 'three'];
console.log([...numbers, ...parts]);




Array.concat()函数



let parts = ['four', 'five'];
let numbers = ['one', 'two', 'three'];
console.log(numbers.concat(parts));




  

两个结果都是一样的。那么,我们想要使用它们的场景是什么?哪一个最适合表现?

7 个答案:

答案 0 :(得分:20)

project/ ├── main └── test ├── integration │   └── SomeTestIT.java └── unit └── SomeTestU.java 也有同样的结果,为什么要在这里使用呢? :P

一般情况下,当你有来自任意来源的两个(或更多)数组时,你会使用console.log(['one', 'two', 'three', 'four', 'five']),如果知道总是属于数组的其他元素,你会在数组文字中使用扩展语法之前。因此,如果您的代码中有一个带有concat的数组文字,那么只需使用扩展语法,然后只使用concat

concat

在处理非数组值时,这两种方案的表现也完全不同。

答案 1 :(得分:20)

正如@Bergi所说,当参数不是数组时,concat和点差非常不同。

当参数不是数组时,concat"数组化"它(即将x转换为[x])并继续使用此临时数组,而...尝试迭代它,如果不能则会失败。考虑:

a = [1, 2, 3]
x = 'hello';

console.log(a.concat(x));  // [ 1, 2, 3, 'hello' ]
console.log([...a, ...x]); // [ 1, 2, 3, 'h', 'e', 'l', 'l', 'o' ]

这里,concat以原子方式处理字符串,而...使用其默认迭代器char-by-char。

另一个例子:

x = 99;

console.log(a.concat(x));   // [1, 2, 3, 99]
console.log([...a, ...x]);  // TypeError: x is not iterable

同样,对于concat,数字是一个原子,...尝试迭代它并失败。

最后:

function* gen() { for(let i = 97; i < 100; i++) yield i };

console.log(a.concat(gen()));   // [ 1, 2, 3, {} ]
console.log([...a, ...gen()]);  // [ 1, 2, 3, 97, 98, 99 ]

concat不会尝试迭代生成器并将其作为一个整体追加,而...可以很好地从中获取所有值。

总结一下,当你的参数可能是非数组时,concat...之间的选择取决于你是否希望它们被迭代。

性能方面concat要快得多,可能是因为它可以从特定于阵列的优化中受益,而...必须符合常见的迭代协议。定时:

&#13;
&#13;
let big = (new Array(1e5)).fill(99);
let i, x;

console.time('concat-big');
for(i = 0; i < 1e2; i++) x = [].concat(big)
console.timeEnd('concat-big');

console.time('spread-big');
for(i = 0; i < 1e2; i++) x = [...big]
console.timeEnd('spread-big');


let a = (new Array(1e3)).fill(99);
let b = (new Array(1e3)).fill(99);
let c = (new Array(1e3)).fill(99);
let d = (new Array(1e3)).fill(99);

console.time('concat-many');
for(i = 0; i < 1e2; i++) x = [1,2,3].concat(a, b, c, d)
console.timeEnd('concat-many');

console.time('spread-many');
for(i = 0; i < 1e2; i++) x = [1,2,3, ...a, ...b, ...c, ...d]
console.timeEnd('spread-many');
&#13;
&#13;
&#13;

在最新的Chrome中,concat的速度提高了约5倍。

答案 2 :(得分:3)

关于大阵列的性能,虽然某些答复是正确的,但处理小阵列时的性能却大不相同。

您可以在https://jsperf.com/spread-vs-concat-size-agnostic上亲自检查结果。

如您所见,对于较小的阵列,spread的速度快50%,而对于大型阵列,concat的速度快几倍。

答案 3 :(得分:2)

我认为有一个区别是使用扩展运算符来处理大数组大小会给你Maximum call stack size exceeded错误,你可以避免使用concat运算符。

&#13;
&#13;
var  someArray = new Array(600000);
var newArray = [];
var tempArray = [];


someArray.fill("foo");

try {
  newArray.push(...someArray);
} catch (e) {
  console.log("Using spread operator:", e.message)
}

tempArray = newArray.concat(someArray);
console.log("Using concat function:", tempArray.length)
&#13;
&#13;
&#13;

答案 4 :(得分:1)

concatpush之间有一个非常重要的区别,就是前一个不会突变基础数组,要求您将结果分配给相同或不同的对象数组:

let things = ['a', 'b', 'c'];
let moreThings = ['d', 'e'];
things.concat(moreThings);
console.log(things); // [ 'a', 'b', 'c' ]
things.push(...moreThings);
console.log(things); // [ 'a', 'b', 'c', 'd', 'e' ]

我已经看到由concat更改数组(为朋友说话)的假设引起的错误。

答案 5 :(得分:0)

我只回答性能问题,因为有关方案已经有了很好的答案。我编写了一个测试,并在最新的浏览器上执行了该测试。在结果和代码下方。

/*
 * Performance results.
 * Browser           Spread syntax      concat method
 * --------------------------------------------------
 * Chrome 75         626.43ms           235.13ms
 * Firefox 68        928.40ms           821.30ms
 * Safari 12         165.44ms           152.04ms
 * Edge 18           1784.72ms          703.41ms
 * Opera 62          590.10ms           213.45ms
 * --------------------------------------------------
*/

在我编写和使用的代码下面。

const array1 = [];
const array2 = [];
const mergeCount = 50;
let spreadTime = 0;
let concatTime = 0;

// Used to popolate the arrays to merge with 10.000.000 elements.
for (let i = 0; i < 10000000; ++i) {
    array1.push(i);
    array2.push(i);
}

// The spread syntax performance test.
for (let i = 0; i < mergeCount; ++i) {
    const startTime = performance.now();
    const array3 = [ ...array1, ...array2 ];

    spreadTime += performance.now() - startTime;
}

// The concat performance test.
for (let i = 0; i < mergeCount; ++i) {
    const startTime = performance.now();
    const array3 = array1.concat(array2);

    concatTime += performance.now() - startTime;
}

console.log(spreadTime / mergeCount);
console.log(concatTime / mergeCount);

我还在博客中写了关于该主题的文章: https://www.malgol.com/how-to-merge-two-arrays-in-javascript/

答案 6 :(得分:-3)