Pour dupliquer un tableau en JavaScript: lequel des éléments suivants est le plus rapide à utiliser?
Méthode de tranche
var dup_array = original_array.slice();
For
boucle
for(var i = 0, len = original_array.length; i < len; ++i)
dup_array[i] = original_array[i];
Je sais que les deux façons ne font qu'une copie superficielle : si original_array contient des références à des objets, les objets ne seront pas clonés, mais seules les références seront copiées, et donc les deux tableaux auront des références aux mêmes objets. Mais ce n'est pas le but de cette question.
Je ne demande que de la vitesse.
javascript
arrays
duplicates
copy
slice
Marco Demaio
la source
la source
Réponses:
Il existe au moins 5 (!) Façons de cloner un tableau:
Il y a eu un thread huuuge BENCHMARKS , fournissant les informations suivantes:
pour les navigateurs clignotants
slice()
est la méthode la plus rapide,concat()
un peu plus lente etwhile loop
2,4 fois plus lente.pour les autres navigateurs
while loop
est la méthode la plus rapide, car ces navigateurs n'ont pas d'optimisations internes pourslice
etconcat
.Cela reste vrai en juillet 2016.
Vous trouverez ci-dessous des scripts simples que vous pouvez copier-coller dans la console de votre navigateur et exécuter plusieurs fois pour voir l'image. Ils produisent des millisecondes, plus c'est bas, mieux c'est.
en boucle
tranche
Veuillez noter que ces méthodes cloneront l'objet Array lui-même, cependant le contenu du tableau est copié par référence et n'est pas cloné en profondeur.
la source
splice
et vous serez surpris (pendant que ...)A.map(function(e){return e;});
Techniquement,
slice
c'est le moyen le plus rapide. Cependant , il est encore plus rapide si vous ajoutez l'0
index de début.est plus rapide que
http://jsperf.com/cloning-arrays/3
la source
myArray.slice(0,myArray.length-1);
plus rapide quemyArray.slice(0);
?qu'en est-il de l'es6?
la source
[].concat(_slice.call(arguments))
arguments
ça vient ... Je pense que votre sortie babel regroupe quelques fonctionnalités différentes. C'est plus probablearr2 = [].concat(arr1)
.arr2 = [].conact(arr1)
est différent dearr2 = [...arr1]
.[...arr1]
la syntaxe convertira le trou enundefined
. Par exemplearr1 = Array(1); arr2 = [...arr1]; arr3 = [].concat(arr1); 0 in arr2 !== 0 in arr3
,.n = 1000*1000; start = + new Date(); a = Array(n); b = [...a]; console.log(new Date() - start); // 168
[{a: 'a', b: {c: 'c'}}]
. Sic
la valeur de est modifiée dans le tableau "dupliqué", elle changera dans le tableau d'origine, car ce n'est qu'une copie référentielle, pas un clone.Moyen le plus simple de cloner en profondeur un tableau ou un objet:
la source
undefined
defunction
s. Ces deux éléments seront convertisnull
pour vous au cours duJSON.stringify
processus. D'autres stratégies, telles que celles(['cool','array']).slice()
qui ne les modifieront pas, mais ne clonent pas profondément les objets dans le tableau. Il y a donc un compromis.n = 1000*1000; start = + new Date(); a = Array(n); var b = JSON.parse(JSON.stringify(a)) console.log(new Date() - start); // 221
la source
J'ai monté une démo rapide: http://jsbin.com/agugo3/edit
Mes résultats sur Internet Explorer 8 sont 156, 782 et 750, ce qui indiquerait que
slice
c'est beaucoup plus rapide dans ce cas.la source
a.map(e => e)
est une autre alternative pour ce travail. À ce jour.map()
est très rapide (presque aussi rapide que.slice(0)
) dans Firefox, mais pas dans Chrome.D'un autre côté, si un tableau est multidimensionnel, puisque les tableaux sont des objets et que les objets sont des types de référence, aucune des méthodes slice ou concat ne sera un remède ... Donc, une façon appropriée de cloner un tableau est une invention de
Array.prototype.clone()
as suit.la source
🏁 Le moyen le plus rapide de cloner un tableau
J'ai fait cette fonction utilitaire très simple pour tester le temps qu'il faut pour cloner un tableau. Il n'est pas fiable à 100%, mais il peut vous donner une idée globale du temps nécessaire pour cloner un tableau existant:
Et testé une approche différente:
MISE À JOUR :
Remarque: sur tous, la seule façon de cloner en profondeur un tableau est d'utiliser
JSON.parse(JSON.stringify(arr))
.Cela dit, n'utilisez pas ce qui précède si votre tableau peut inclure des fonctions car il reviendra
null
.Merci @GilEpshtain pour cette mise à jour .
la source
arr => arr.slice()
c'est le plus rapide.JSON.parse(JSON.stringify([function(){}]))
affichera[null]
[...arr]
avec4.653076171875ms
dans Chrome et8.565ms
dans Safari. Le deuxième rapide dans Chrome est la fonction tranchearr.slice()
avec6.162109375ms
et dans Safari le second est[].concat(arr)
avec13.018ms
.Jetez un oeil à: lien . Ce n'est pas une question de vitesse, mais de confort. De plus, comme vous pouvez le voir, vous ne pouvez utiliser la tranche (0) que sur les types primitifs .
Pour créer une copie indépendante d'un tableau plutôt qu'une copie de la référence, vous pouvez utiliser la méthode de tranche de tableau.
Exemple:
Source: lien
la source
for
boucle de la question.Comme @Dan l'a dit "Cette réponse devient rapidement obsolète. Utilisez des repères pour vérifier la situation réelle", il y a une réponse spécifique de jsperf qui n'a pas eu de réponse pour elle-même: tandis que :
avait 960 589 ops / sec avec le runnerup
a.concat()
à 578,129 ops / sec, qui est 60%.Il s'agit du dernier Firefox (40) 64 bits.
@aleclarson a créé une nouvelle référence plus fiable.
la source
ECMAScript 2015 façon avec l'
Spread
opérateur:Exemples de base:
Essayez dans la console du navigateur:
Références
la source
Cela dépend du navigateur. Si vous regardez dans le billet de blog Array.prototype.slice vs la création manuelle de tableaux , il existe un guide approximatif des performances de chacun:
Résultats:
la source
arguments
n'est pas un tableau approprié et il utilisecall
pour forcer l'slice
exécution sur la collection. les résultats peuvent être trompeurs.Il existe une solution beaucoup plus propre:
La vérification de la longueur est requise, car le
Array
constructeur se comporte différemment lorsqu'il est appelé avec exactement un argument.la source
splice()
, peut-être. Mais vraiment, appliquer et c'est tout sauf intuitive.Array.of
et ignorer la longueur:Array.of.apply(Array, array)
N'oubliez pas que .slice () ne fonctionnera pas pour les tableaux à deux dimensions. Vous aurez besoin d'une fonction comme celle-ci:
la source
Cela dépend de la longueur du tableau. Si la longueur du tableau est <= 1 000 000, les méthodes
slice
etconcat
prennent environ le même temps. Mais quand vous donnez une gamme plus large, laconcat
méthode gagne.Par exemple, essayez ce code:
Si vous définissez la longueur de original_array sur 1 000 000, la
slice
méthode etconcat
méthode prennent approximativement le même temps (3 à 4 ms, selon les nombres aléatoires).Si vous définissez la longueur de original_array sur 10 000 000, la
slice
méthode prend plus de 60 ms et laconcat
méthode prend plus de 20 ms.la source
dup.push
est inacceptablea5
, au lieudup[i] =
devrait être utiliséUne solution simple:
la source
Donc, pour éviter que ces scénarios ne se produisent, utilisez
la source
cloneNums[0][0]
de votre exemple a propagé la modificationnums[0][0]
- mais c'est parce quenums[0][0]
c'est effectivement un objet dont la référence est copiée danscloneNums
par l'opérateur de propagation. Tout cela pour dire que ce comportement n'affectera pas le code où nous copions par valeur (int, chaîne etc littéraux).Temps de référence!
Mes résultats:
Chrome (moteur V8):
Firefox (moteur SpiderMonkey):
la source
Des moyens rapides de dupliquer un tableau en JavaScript dans l'ordre:
#1: array1copy = [...array1];
#2: array1copy = array1.slice(0);
#3: array1copy = array1.slice();
Si vos objets tableau contiennent du contenu non sérialisable JSON (fonctions, Number.POSITIVE_INFINITY, etc.), mieux utiliser
array1copy = JSON.parse(JSON.stringify(array1))
la source
Vous pouvez suivre ce code. Clone de tableau de façon immuable. C'est le moyen idéal pour cloner un tableau
la source
Dans ES6, vous pouvez simplement utiliser la syntaxe Spread .
Exemple:
Veuillez noter que l'opérateur d'étalement génère un tout nouveau tableau, donc la modification de l'un n'affectera pas l'autre.
Exemple:
la source