140 votes

opérateur de diffusion vs array.concat ()

Quelle est la différence entre spread operator et array.concat()

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

Tableau.concat() la fonction

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

Les deux résultats sont identiques. Donc, quel type de scénarios que nous voulons les utiliser? Et qui est le mieux pour la performance?

232voto

georg Points 52691

Comme @Bergi dit, concat et les marges sont très différentes si l'argument n'est pas un tableau.

Si l'argument n'est pas un tableau, concat ajoute comme un tout, ... tente de le parcourir et échoue si elle ne peut pas. Considérer:

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' ]

Ici, concat traite la chaîne de façon atomique, alors que ... utilise sa valeur par défaut itérateur, char par char.

Un autre exemple:

x = 99;

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

Encore une fois, pour concat le nombre est un atome, ... tente de le parcourir et d'échec.

Enfin:

function* gen() { yield *'abc' }

console.log(a.concat(gen()));   // [ 1, 2, 3, Object [Generator] {} ]
console.log([...a, ...gen()]);  // [ 1, 2, 3, 'a', 'b', 'c' ]

concat ne fait aucune tentative pour itérer le générateur et l'ajoute comme un tout, ... bien récupère toutes les valeurs.

Pour résumer, lorsque vos arguments sont peut-être non-ensembles, le choix entre concat et ... dépend si vous voulez être répétées.

Le ci-dessus décrit le comportement par défaut de concat, cependant, ES6 fournit un moyen de le remplacer avec de l' Symbol.isConcatSpreadable. Par défaut, ce symbole est - true pour les tableaux, et false pour tout le reste. Le paramètre true dit concat pour itérer l'argument, tout comme ... n'est:

str = 'hello'
console.log([1,2,3].concat(str)) // [1,2,3, 'hello']

str = new String('hello');
str[Symbol.isConcatSpreadable] = true;
console.log([1,2,3].concat(str)) // [ 1, 2, 3, 'h', 'e', 'l', 'l', 'o' ]

Performance sage- concat est plus rapide, probablement parce qu'il peut bénéficier de la matrice optimisations spécifiques, tandis que d' ... doit être conforme à la commune itération protocole. Horaires:

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');

78voto

Bergi Points 104242

Bien console.log(['one', 'two', 'three', 'four', 'five']) a le même effet que de bien, alors pourquoi utiliser ici? :P

En général, vous utiliserez concat quand vous avez deux (ou plus) des tableaux à partir de sources arbitraires, et vous devez utiliser la propagation de la syntaxe dans le littéral de tableau, si les autres éléments qui font toujours partie de la matrice sont connus avant. Donc, si vous avez un littéral de tableau avec concat dans votre code, il suffit d'aller pour la propagation de la syntaxe, et il suffit d'utiliser concat autrement:

[...a, ...b] // bad :-(
a.concat(b) // good :-)

[x, y].concat(a) // bad :-(
[x, y, ...a]    // good :-)

Aussi les deux solutions se comportent différemment lorsqu'ils traitent avec des non-valeurs de tableau.

72voto

Je réponds juste à la question de la performance puisqu'il y a déjà de bonnes réponses concernant les scénarios. J'ai écrit un essai et exécuté sur les navigateurs les plus récents. Ci-dessous les résultats et le code.

/*
 * 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
 * --------------------------------------------------
*/

Ci-dessous le code que j'ai écrit et utilisé.

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);

J'ai aussi écrit sur le sujet dans mon blog: https://www.malgol.com/how-to-merge-two-arrays-in-javascript/.

14voto

Ankit Agarwal Points 23887

La seule différence que je pense est valable est que l'utilisation de l'opérateur d'étalement pour une grande taille de tableau vous donnera une erreur de Maximum call stack size exceeded que vous pouvez éviter d'utiliser l'opérateur concat .

 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) 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X