Quelle est la différence entre spread operator
Et array.concat()
let parts = ['four', 'five'];
let numbers = ['one', 'two', 'three'];
console.log([...numbers, ...parts]);
Fonction Array.concat ()
let parts = ['four', 'five'];
let numbers = ['one', 'two', 'three'];
console.log(numbers.concat(parts));
Les deux résultats sont les mêmes. Alors, quel genre de scénarios nous voulons utiliser? Et quel est le meilleur pour la performance?
Bien console.log(['one', 'two', 'three', 'four', 'five'])
a le même résultat, alors pourquoi utiliser soit ici? : P
En général, vous utiliseriez concat
lorsque vous avez deux (ou plusieurs) tableaux de sources arbitraires, et vous utiliseriez la syntaxe de propagation dans le littéral de tableau si les éléments supplémentaires qui font toujours partie du tableau sont connus auparavant. Donc, si vous aviez un littéral de tableau avec concat
dans votre code, utilisez simplement la syntaxe spread et utilisez simplement concat
sinon:
[...a, ...b] // bad :-(
a.concat(b) // good :-)
[x, y].concat(a) // bad :-(
[x, y, ...a] // good :-)
De plus, les deux alternatives se comportent différemment lorsqu'il s'agit de valeurs autres que des tableaux.
Comme @Bergi l'a dit, concat
et les spreads sont très différents lorsque l'argument n'est pas un tableau.
Lorsque l’argument n’est pas un tableau, concat
"le rend" (c’est-à-dire qu'il convertit x
en [x]
) et continue avec ce tableau temporaire, tandis que ...
tente de l'itérer et échoue s'il ne le 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 manière atomique, tandis que ...
utilise son itérateur par défaut, caractère par caractère.
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 échoue.
Finalement:
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
n'effectue aucune tentative pour itérer le générateur et l'ajoute dans son ensemble, tandis que ...
récupère joliment toutes les valeurs.
Pour résumer, lorsque vos arguments sont éventuellement non-tableaux, le choix entre concat
et ...
dépend de si vous voulez qu’ils soient itérés.
En termes de performances, concat
est plus rapide, probablement parce qu'il peut tirer parti d'optimisations spécifiques aux tableaux, tandis que ...
doit être conforme au protocole d’itération commun. 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');
La seule différence que je pense être valable est que l'utilisation de l'opérateur spread pour une taille de tableau importante génère une erreur de Maximum call stack size exceeded
, Ce que vous pouvez éviter en utilisant 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)
Je réponds simplement à la question de performance car il existe déjà de bonnes réponses concernant les scénarios. J'ai écrit un test et l'ai 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 également écrit sur le sujet dans mon blog: https://www.malgol.com/how-to-merge-two-arrays-in-javascript/ .