Quel est le moyen le plus rapide de parcourir un tableau en JavaScript?

249

J'ai appris des livres que vous devriez écrire pour une boucle comme celle-ci:

for(var i=0, len=arr.length; i < len; i++){
    // blah blah
}

donc le arr.lengthne sera pas calculé à chaque fois.

D'autres disent que le compilateur optimisera cela, vous pouvez donc simplement écrire:

for(var i=0; i < arr.length; i++){
    // blah blah
}

Je veux juste savoir quelle est la meilleure façon de pratiquer?

wong2
la source
1
vaut également le coup d'oeil lors du traitement du bouclage de tableaux: jsperf.com/array-loop-var-caching
cloakedninjas
@ wong2 Ce benchmark de Browserdiet a une collection plus complète d'alternatives.
Domi
1
jsben.ch/#/y3SpC
EscapeNetscape
Amélioré par rapport au jsben précédent: jsben.ch/#/R6LbS
Corbfon
Pouvons-nous introduire la for ... ofboucle à ce concours? La syntaxe semble encore plus simple qu'une boucle for sans mise en cache, et je veux savoir si je devrais passer à l'utilisation des boucles for.
programmerRaj

Réponses:

339

Après avoir effectué ce test avec la plupart des navigateurs modernes ...

http://jsben.ch/dyM52

Actuellement , la forme de boucle la plus rapide (et à mon avis la plus syntaxiquement évidente).

une norme pour la boucle avec la mise en cache de la longueur

for (var i = 0, len = myArray.length; i < len; i++) {

}

Je dirais que c'est certainement un cas où j'applaudis les développeurs de moteurs JavaScript. Un temps d'exécution doit être optimisé pour plus de clarté , pas d'intelligence .

jondavidjohn
la source
6
Fait intéressant, dans IE9, c'est plus rapide: pour (var i = 0, len = myArray.length; i <len; ++ i) {} // préfixe incr, au lieu de postfix
Christopher Bennage
4
Voir Préférer les opérateurs de préfixe à postfix pour d'autres raisons d'utiliser ++i.
Bennett McElwee
4
J'ai testé en utilisant l'opérateur de préfixe comme @BennettMcElwee l'a suggéré et cela fonctionne un peu plus vite: for(var i=0, len=myArray.length; i<len; ++i) Vérifiez jsperf.com/caching-array-length/84
victmo
21
Vous devez être prudent en utilisant cette boucle. J'ai commencé à l'utiliser et j'ai eu un bug difficile à suivre à cause d'une erreur que j'ai commise. Si vous imbriquez deux boucles comme celle-ci: jsfiddle.net/KQwmL/1 . Vous devez faire attention à nommer la var len différemment dans les deux boucles, sinon la deuxième boucle écrasera la première len.
Rui Marques
6
@WillshawMedia Vous pouvez déclarer plusieurs variables avec une seule varinstruction. La façon dont il est écrit lenest en fait délimitée comme vous le suggérez.
jondavidjohn
90

Le moyen le plus rapide absolu de parcourir un tableau javascript est:

var len = arr.length;
while (len--) {
    // blah blah
}

Voir http://blogs.oracle.com/greimer/entry/best_way_to_code_a pour une comparaison complète

gnur
la source
1
N'oubliez pas d'utiliser var(sinon lendevient une variable globale). Voir également jsperf.com/loops pour plus de repères de boucle.
Mathias Bynens
22
Le billet de blog sur lequel cette réponse est basée a maintenant près de 4 ans, et beaucoup de choses ont changé dans les moteurs js pendant cette période, voir ma réponse ci-dessous pour une comparaison mise à jour.
jondavidjohn
1
Je suis d'accord avec @jondavidjohn. J'ai testé ce code et il s'est avéré être le moins efficace ... Vérifiez jsperf.com/caching-array-length/84
victmo
La réponse ci-dessus est presque universellement (sur tous les navigateurs) beaucoup plus lente qu'une boucle for. Voir le lien JSPerf dans la réponse acceptée. C'est une grande honte, car il est extrêmement lisible IMO.
Letharion
3
Je suppose que @jondavidjohn que ce que vous entendez par «ma réponse ci-dessous» est «ma réponse ci-dessus» lol.
Shanimal
40

En juin 2016 , faire des tests dans le dernier Chrome (71% du marché des navigateurs en mai 2016 et en augmentation):

  • La boucle la plus rapide est une boucle for , avec et sans longueur de mise en cache, offrant des performances vraiment similaires. (La boucle for avec une longueur en cache a parfois donné de meilleurs résultats que celle sans mise en cache, mais la différence est presque négligeable, ce qui signifie que le moteur peut déjà être optimisé pour favoriser la boucle standard et probablement la plus simple pour la boucle sans mise en cache).
  • La boucle while avec décrémentations était environ 1,5 fois plus lente que la boucle for.
  • Une boucle utilisant une fonction de rappel (comme la norme forEach), était environ 10 fois plus lente que la boucle for.

Je pense que ce fil est trop ancien et qu'il est trompeur pour les programmeurs de penser qu'ils doivent mettre en cache la longueur, ou utiliser des whiles à travers inverse avec des décrémentations pour obtenir de meilleures performances, en écrivant du code moins lisible et plus sujet aux erreurs qu'un simple simple pour la boucle. Par conséquent, je recommande:

  • Si votre application parcourt de nombreux éléments ou si votre code de boucle se trouve dans une fonction souvent utilisée, une boucle simple pour la réponse est la réponse:

    for (var i = 0; i < arr.length; i++) {
      // Do stuff with arr[i] or i
    }
  • Si votre application ne parcourt pas vraiment beaucoup d'éléments ou si vous avez juste besoin de faire de petites itérations ici et là, l'utilisation du rappel standard forEach ou de toute fonction similaire de la bibliothèque JS de votre choix pourrait être plus compréhensible et moins sujette aux erreurs, car la portée de la variable d'index est fermée et vous n'avez pas besoin d'utiliser de crochets, pour accéder directement à la valeur du tableau:

    arr.forEach(function(value, index) {
      // Do stuff with value or index
    });
  • Si vous avez vraiment besoin de gratter quelques millisecondes tout en itérant sur des milliards de lignes et que la longueur de votre tableau ne change pas au cours du processus, vous pouvez envisager de mettre en cache la longueur dans votre boucle for. Bien que je pense que ce n'est vraiment pas nécessaire de nos jours:

    for (var i = 0, len = arr.length; i < len; i++) {
      // Do stuff with arr[i]
    }
CGodo
la source
Nan. jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 montre que le plus rapide est "Boucle inversée, comparaison implicite, code en ligne" (105 221 ops / sec) tandis que "Boucle, valeur en cache, code en ligne" n'a marqué que 76 635 ops / sec (Chrome 38.0.2125.111 )
Fr0sT
@ Fr0sT Votre benchmark est un scénario différent, traversant des tableaux de l'index 1 à <= la longueur. Bien sûr, cela va conduire à des résultats différents. Si vous essayez de traverser des tableaux à base zéro avec <longueur - ce qui me semble être le scénario habituel - vous découvrirez que les résultats sont mieux optimisés avec une boucle "pour" normale (avec une longueur en cache légèrement plus rapide).
CGodo
Kyopaxa a changé les repères en (0 <= i <longueur), les résultats sont les mêmes. "Boucle inversée, comparaison implicite, appel de fonction" a marqué 365 kops / sec, tandis que "Boucle, valeur mise en cache, code intégré" a marqué 350 kops / sec (FF 51)
Fr0sT
@ Fr0sT si vous modifiez les boucles for en cache de base zéro sans comparaison égale, telles que for(let i=0, j=array.length; i < j; i++)les boucles for for forward accélèrent considérablement. Sur quelques tests, j'ai couru, il a gagné, sur la plupart c'était dans la marge d'erreur ou la boucle inverse.
Isaac B
1
@IsaacB et tout, désolé, je n'ai pas remarqué que le banc est tout à fait incorrect - toutes les boucles directes itèrent 1..length tandis que les boucles inverses itèrent length..0 (l'élément arr [length] n'est pas valide). J'ai corrigé les tests et maintenant ils affichent les résultats suivants: "Boucle, code en ligne" 360 616 ops / sec ± 0,27%, "Boucle, valeur en cache, code en ligne" 345 786 ops / sec ± 2,18% (Sic!) "Boucle inversée, comparaison implicite, code en ligne "322 640 opérations / sec ± 2,90% (!!!). Les tests ont été exécutés par FF51. Le nouveau banc est ici jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570 . Il semble donc que cela n'ait aucun sens d'uglifier les boucles.
Fr0sT
31

Si la commande n'est pas importante, je préfère ce style:

for(var i = array.length; i--; )

Il met en cache la longueur et est beaucoup plus court à écrire. Mais il parcourra le tableau dans l'ordre inverse.

Felix Kling
la source
6
Vous venez de le tuer.
Vignesh Raja
n'avez-vous pas besoin de i> = 0 ;?
MarwaAhmad
3
@MarwaAhmad: Non. Renvoie i--un nombre et une fois que le nombre est 0la condition c'est falseparce que Boolean(0) === false.
Felix Kling
31

C'est juste 2018 donc une mise à jour pourrait être sympa ...

Et je dois vraiment être en désaccord avec la réponse acceptée . Il diffère sur différents navigateurs. certains font forEachplus vite, certains for-loop, et certains while voici une référence sur toutes les méthodes http://jsben.ch/mW36e

arr.forEach( a => {
  // ...
}

et puisque vous pouvez voir beaucoup de for-loop comme for(a = 0; ... )alors vaut la peine de mentionner que sans les variables "var" seront définies globalement et cela peut considérablement affecter la vitesse, donc ça va ralentir.

L'appareil de Duff fonctionne plus rapidement sur l'opéra mais pas sur Firefox

var arr = arr = new Array(11111111).fill(255);
var benches =     
[ [ "empty", () => {
  for(var a = 0, l = arr.length; a < l; a++);
}]
, ["for-loop", () => {
  for(var a = 0, l = arr.length; a < l; ++a)
    var b = arr[a] + 1;
}]
, ["for-loop++", () => {
  for(var a = 0, l = arr.length; a < l; a++)
    var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () => {
  for(var a = 0; a < arr.length; ++a )
    var b = arr[a] + 1;
}]
, ["reverse for-loop", () => {
  for(var a = arr.length - 1; a >= 0; --a )
    var b = arr[a] + 1;
}]
,["while-loop", () => {
  var a = 0, l = arr.length;
  while( a < l ) {
    var b = arr[a] + 1;
    ++a;
  }
}]
, ["reverse-do-while-loop", () => {
  var a = arr.length - 1; // CAREFUL
  do {
    var b = arr[a] + 1;
  } while(a--);   
}]
, ["forEach", () => {
  arr.forEach( a => {
    var b = a + 1;
  });
}]
, ["for const..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( const a in ar ) {
    var b = a + 1;
  }
}]
, ["for let..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( let a in ar ) {
    var b = a + 1;
  }
}]
, ["for var..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( var a in ar ) {
    var b = a + 1;
  }
}]
, ["Duff's device", () => {
  var len = arr.length;
  var i, n = len % 8 - 1;

  if (n > 0) {
    do {
      var b = arr[len-n] + 1;
    } while (--n); // n must be greater than 0 here
  }
  n = (len * 0.125) ^ 0;
  if (n > 0) { 
    do {
      i = --n <<3;
      var b = arr[i] + 1;
      var c = arr[i+1] + 1;
      var d = arr[i+2] + 1;
      var e = arr[i+3] + 1;
      var f = arr[i+4] + 1;
      var g = arr[i+5] + 1;
      var h = arr[i+6] + 1;
      var k = arr[i+7] + 1;
    }
    while (n); // n must be greater than 0 here also
  }
}]];
function bench(title, f) {
  var t0 = performance.now();
  var res = f();
  return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
var globalVarTime = bench( "for-loop without 'var'", () => {
  // Here if you forget to put 'var' so variables'll be global
  for(a = 0, l = arr.length; a < l; ++a)
     var b = arr[a] + 1;
});
var times = benches.map( function(a) {
                      arr = new Array(11111111).fill(255);
                      return [a[0], bench(...a)]
                     }).sort( (a,b) => a[1]-b[1] );
var max = times[times.length-1][1];
times = times.map( a => {a[2] = (a[1]/max)*100; return a; } );
var template = (title, time, n) =>
  `<div>` +
    `<span>${title} &nbsp;</span>` +
    `<span style="width:${3+n/2}%">&nbsp;${Number(time.toFixed(3))}msec</span>` +
  `</div>`;

var strRes = times.map( t => template(...t) ).join("\n") + 
            `<br><br>for-loop without 'var' ${globalVarTime} msec.`;
var $container = document.getElementById("container");
$container.innerHTML = strRes;
body { color:#fff; background:#333; font-family:helvetica; }
body > div > div {  clear:both   }
body > div > div > span {
  float:left;
  width:43%;
  margin:3px 0;
  text-align:right;
}
body > div > div > span:nth-child(2) {
  text-align:left;
  background:darkorange;
  animation:showup .37s .111s;
  -webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
<div id="container"> </div>

nullqube
la source
3
@Maykonn vous vouliez probablement dire "et ça marche partout sauf Opera Mini"
dube
3
@Maykonn qui n'est pas répertorié dans la vue par défaut car 0,18% de tous les utilisateurs ont IE8 et vous ne devriez pas perdre de temps à essayer de le prendre en charge; en 2018 c'est un cheval mort.
dube
1
C'est certainement vrai si vous considérez tous les utilisateurs du monde entier. Mais, malheureusement, dans certaines parties du monde, IE8 est encore pertinent.
Maykonn
1
Si je peux me permettre, non seulement différents navigateurs auront des résultats différents avec des méthodes différentes, mais les mêmes navigateurs auront des résultats différents avec des entrées différentes. Un énorme tableau uniquement numérique sera très optimisé, tandis qu'un petit mixte ne le sera pas.
Kaiido
1
@Tahlil Merci.
nullqube
19

2014 Whileest de retour

Pensez simplement logique.

Regarde ça

for( var index = 0 , length = array.length ; index < length ; index++ ) {

 //do stuff

}
  1. Besoin de créer au moins 2 variables (index, longueur)
  2. Besoin de vérifier si l'indice est plus petit que la longueur
  3. Besoin d'augmenter l'indice
  4. la forboucle a 3 paramètres

Maintenant, dites-moi pourquoi cela devrait être plus rapide que:

var length = array.length;

while( --length ) { //or length--

 //do stuff

}
  1. Une variable
  2. Pas de chèques
  3. l'indice est diminué (les machines préfèrent cela)
  4. while n'a qu'un seul paramètre

J'étais totalement confus lorsque Chrome 28 a montré que la boucle for est plus rapide que le temps. Cela doit avoir ben une sorte de

"Euh, tout le monde utilise la boucle for, concentrons-nous sur cela lors du développement pour Chrome."

Mais maintenant, en 2014, la boucle while est de retour sur le chrome. c'est 2 fois plus rapide, sur les autres navigateurs / anciens, c'était toujours plus rapide.

Dernièrement, j'ai fait de nouveaux tests. Maintenant, dans le monde réel, ces codes courts ne valent rien et jsperf ne peut pas réellement exécuter correctement la boucle while, car il doit recréer le array.length, ce qui prend également du temps.

vous ne pouvez pas obtenir la vitesse réelle d'une boucle while sur jsperf.

vous devez créer votre propre fonction personnalisée et vérifier cela avec window.performance.now()

Et oui ... il n'y a aucun moyen que la boucle while soit simplement plus rapide.

Le vrai problème est en fait la manipulation du dom / le temps de rendu / le temps de dessin ou comment vous voulez l'appeler.

Par exemple, j'ai une scène de toile où j'ai besoin de calculer les coordonnées et les collisions ... cela se fait entre 10-200 MicroSecondes (pas millisecondes). il faut en fait plusieurs millisecondes pour tout rendre. Tout comme dans DOM.

MAIS

Il existe une autre manière super performante d'utiliser le for loopdans certains cas ... par exemple pour copier / cloner un tableau

for(
 var i = array.length ;
 i > 0 ;
 arrayCopy[ --i ] = array[ i ] // doing stuff
);

Remarquez la configuration des paramètres:

  1. Identique à la boucle while, j'utilise une seule variable
  2. Besoin de vérifier si l'indice est supérieur à 0;
  3. Comme vous pouvez le voir, cette approche est différente de la normale pour la boucle que tout le monde utilise, car je fais des choses à l'intérieur du 3ème paramètre et je diminue également directement à l'intérieur du tableau.

Cela dit, cela confirme que des machines comme le -

en écrivant que je pensais à le raccourcir un peu et à supprimer des trucs inutiles et j'ai écrit celui-ci en utilisant le même style:

for(
 var i = array.length ;
 i-- ;
 arrayCopy[ i ] = array[ i ] // doing stuff
);

Même s'il est plus court, il semble que l'utilisation d' iune fois de plus ralentit tout. C'est 1/5 plus lent que la forboucle précédente et celle- whilelà.

Remarque: le ;est très important après le pour looo sans{}

Même si je viens de vous dire que jsperf n'est pas le meilleur moyen de tester des scripts .. j'ai ajouté ces 2 boucles ici

http://jsperf.com/caching-array-length/40

Et voici une autre réponse sur les performances en javascript

https://stackoverflow.com/a/21353032/2450730

Cette réponse est de montrer des façons d'écrire javascript performantes. Donc, si vous ne pouvez pas lire cela, demandez et vous obtiendrez une réponse ou lirez un livre sur javascript http://www.ecma-international.org/ecma-262/5.1/

cocco
la source
Cette réponse commence très bien . J'ai remarqué que les deux dernières années, le forétait plus rapide que le while, et j'ai lu une fois sur crome-dev, c'était exactement pour la raison que vous mentionnez. Ce ne serait qu'une question de temps avant de whilerattraper son retard. À partir de là, la logique de la première partie de votre réponse tiendra (encore une fois, oui)! Cependant, les implémentations modernes ne suivent plus rigoureusement chaque étape spécifiée par ecma (elles sont optimisées). Puisque maintenant votre moteur n'est plus le goulot d'étranglement le plus visible, on peut désormais remarquer les manquements de cache CPU dans les boucles inverses !
GitaarLAB
Expliquez, alors je peux peut-être corriger la réponse ou apprendre quelque chose de nouveau. btw la réponse a maintenant plus d'un an ... les navigateurs peuvent avoir changé avec le temps comme ils le font toujours ...
cocco
À mon avis, alors que (--length) est mauvais parce que si cela fonctionne techniquement parce que 0 est faux, 0 et faux ne sont pas vraiment vraiment la même chose sémantiquement parlant.
scott.korin
ouais ... c'est un article plus ancien maintenant ... mais ouais j'aime la simplicité de tout. Et bien sûr, comme vous le mentionnez dans les deux cas, vous devez savoir quoi écrire. De l'autre côté, je n'ai jamais eu la nécessité de boucler des nombres négatifs.
cocco
9
"les machines préfèrent cela" sonne comme une phrase d'une annonce pour un détergent à lessive
CocoaBean
11

http://jsperf.com/caching-array-length/60

La dernière révision de test, que j'ai préparée (en réutilisant une ancienne), montre une chose.

La longueur de la mise en cache n'est pas très importante, mais elle ne nuit pas.

Chaque première exécution du test lié ci-dessus (sur l'onglet fraîchement ouvert) donne les meilleurs résultats pour les 4 derniers extraits (3e, 5e, 7e et 10e dans les graphiques) dans Chrome, Opera et Firefox dans mon Debian Squeeze 64 bits ( mon matériel de bureau ). Les exécutions suivantes donnent un résultat assez différent.

Les conclusions en termes de performances sont simples:

  • Allez avec pour la boucle (avant) et testez en utilisant !==au lieu de <.
  • Si vous n'avez pas à réutiliser le tableau plus tard, alors la boucle while sur la longueur décrémentée et le shift()tableau destructif sont également efficaces.

tl; dr

De nos jours (2011.10), le schéma ci-dessous semble être le plus rapide.

for (var i = 0, len = arr.length; i !== len; i++) {
    ...
}

Gardez à l'esprit que la mise en cache arr.lengthn'est pas cruciale ici, vous pouvez donc simplement tester i !== arr.lengthet les performances ne chuteront pas, mais vous obtiendrez un code plus court.


PS: Je sais que dans l'extrait de code avec shift()son résultat pourrait être utilisé au lieu d'accéder au 0ème élément, mais j'ai en quelque sorte ignoré cela après avoir réutilisé la révision précédente (qui avait des boucles while incorrectes), et plus tard, je ne voulais pas perdre les résultats déjà obtenus.

przemoc
la source
Créer une variable à l'intérieur de la boucle comme let current = arr [i] peut réduire les performances (grande allocation de mémoire)? Ou serait-il préférable de déclarer le courant avant la boucle? Ou utiliser arr [i] à tous les endroits de la boucle?
Makarov Sergey
8

"Le meilleur" comme en pure performance? ou performance ET lisibilité?

La meilleure performance pure est celle-ci, qui utilise un cache et l'opérateur de préfixe ++ (mes données: http://jsperf.com/caching-array-length/189 )

for (var i = 0, len = myArray.length; i < len; ++i) {
  // blah blah
}

Je dirais que la boucle for sans cache est le meilleur équilibre entre le temps d'exécution et le temps de lecture du programmeur. Chaque programmeur qui a commencé avec C / C ++ / Java ne perdra pas un ms à lire celui-ci

for(var i=0; i < arr.length; i++){
  // blah blah
}
valbaca
la source
2
+1 pour la lisibilité. Peu importe le lennom, il faudrait toujours faire une double prise sur cette première boucle. L'intention de la deuxième boucle est évidente.
Josh Johnson
7

** cache la longueur du tableau à l'intérieur de la boucle, quelques secondes seront éludées. Dépend des éléments dans le tableau s'il y a plus d'éléments dans le tableau, il y a une différence majeure par rapport à Ms de temps *

**

sArr; //Array[158];

for(var i = 0 ; i <sArr.length ; i++) {
 callArray(sArr[i]); //function call
}

***end: 6.875ms***

**

**

sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
  callArray(sArr[i]); //function call
}

***end: 1.354ms***

**

Shushanth Pallegar
la source
6

Cela semble être de loin le moyen le plus rapide ...

var el;
while (el = arr.shift()) {
  el *= 2;
}

Tenez compte du fait que cela consommera le tableau, le mangera et ne laissera plus rien ...

Sergio
la source
2
arr.shift();au lieu de arr.pop() sorte que l'inverse du tableau puisse être évité.
Tintu C Raju
1
@Gargaroz si vous obtenez un JSON à partir d'un service Web, par exemple un service de chat ou des articles sur un catalogue de produits. Une autre situation où vous avez juste besoin d'utiliser le tableau une fois peut être par exemple un graphique qui obtient de nombreuses coordonnées sur une base intervall. Il existe de nombreux exemples.
Sergio
Cool, merci pour l'explication, très gentil de votre part; pouvez-vous me diriger dans la direction où je peux trouver d'autres exemples pour exploiter ce type de boucle?
Gargaroz
1
Actuellement dans Chrome 53 et Firefox 48, c'est l'une des approches les plus lentes - consultez perfjs.info/array-iteration
Pencroff
1
@Alireza d'accord, j'ai aussi un commentaire à faire dans ma réponse.
Sergio
4

C'est l'année 2017 .

J'ai fait quelques tests.

https://jsperf.com/fastest-way-to-iterate-through-an-array/

Il semble que la whileméthode soit la plus rapide sur Chrome.

On dirait que le décrément gauche ( --i) est beaucoup plus rapide que les autres ( ++i, i--,i++ ) sur Firefox.

Cette approche est le jeûne en moyenne. Mais il itère le tableau dans l'ordre inverse.

let i = array.length;
while (--i >= 0) {
    doSomething(array[i]);
}

Si l'ordre à terme est important, utilisez cette approche.

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}
SeregPie
la source
3
En utilisant le mot-clé, letvous comparez réellement les performances de création d'étendue au lieu des performances de boucle. L'utilisation let i = 0, ii = array.lengthde vos forboucles créera une nouvelle portée pour ces variables à l'intérieur du forbloc. Vos whileexemples ne créent pas de nouvelle portée pour les variables à l'intérieur du whilebloc et c'est pourquoi elles sont plus rapides. Si vous utilisez varau lieu de letdans vos boucles for, vous verrez comment les boucles for sont toujours aussi rapides qu'en 2017, mais plus lisibles.
CGodo
Voici un aperçu de ce dont je parle: jsperf.com/javascript-loop-testing-let-vs-var
CGodo
Ce n'est qu'un problème dans Chrome. Dans d'autres navigateurs varet letont les mêmes performances - stackoverflow.com/a/32345435/1785975
SeregPie
Intéressant. Quoi qu'il en soit, je ne trouve pas whileexacte la déclaration "d' être plus rapide dans Chrome". Ce n'est que si vous l'utilisez en letraison de problèmes de performances de ce mot clé dans Chrome. Si vous utilisez varou avec d'autres navigateurs, foret qu'ils whilesont à peu près les mêmes, cela forest parfois encore plus rapide en fonction de la référence, et il est plus compact et lisible à mon humble avis.
CGodo
2

J'écris toujours dans le premier style.

Même si un compilateur est assez intelligent pour l'optimiser pour les tableaux, mais quand même intelligent si nous utilisons DOMNodeList ici ou un objet compliqué avec une longueur calculée?

Je sais quelle est la question des tableaux, mais je pense que c'est une bonne pratique d'écrire toutes vos boucles dans un même style.

Olegas
la source
1
var arr = []; // The array
var i = 0;
while (i < arr.length) {
    // Do something with arr[i]
    i++;
}

i ++ est plus rapide que ++ i, --i et i--

En outre, vous pouvez enregistrer la dernière ligne en faisant arr [i ++] la dernière fois que vous devez accéder à i (mais cela peut être difficile à déboguer).

Vous pouvez le tester ici (avec d'autres tests de boucle): http://jsperf.com/for-vs-ilstpop/5

Forestrf
la source
1
Actuellement dans Chrome 53, c'est vrai, mais Firefox 48 a la même vitesse - consultez perfjs.info/array-iteration
Pencroff
thunderguy.com/semicolon/2002/08/13/… dit que ++ic'est plus rapide ...
IMTheNachoMan
1

En septembre 2017, ces tests jsperf montrent que le modèle suivant est le plus performant sur Chrome 60:

function foo(x) {
 x;
};
arr.forEach(foo);

Quelqu'un est-il capable de se reproduire?

John Vandivier
la source
Oui, il semble être le plus rapide, mais essayez de l'exécuter dans IE11 et ces options sont les plus lentes. Et dans Firefox 55.03, le `` vieux len en cache éclaté '' atteint 12mil, une performance stupéfiante par rapport aux 3,3k de chrome. Pour être cohérent dans les performances de tous les navigateurs, vous devez utiliser la boucle moyenne la plus rapide pour chaque navigateur.
Plippie
0

J'ai essayé d'autres façons d'itérer un énorme tableau et j'ai découvert que la réduction de moitié de la longueur du tableau, puis l'itération des deux moitiés en une seule boucle est plus rapide. Cette différence de performances peut être observée lors du traitement d' énormes tableaux .

var firstHalfLen =0;
var secondHalfLen = 0;
var count2=0;
var searchterm = "face";
var halfLen = arrayLength/2;
if(arrayLength%2==halfLen)
{
   firstHalfLen = Math.ceil(halfLen);
   secondHalfLen=Math.floor(halfLen);
}
else
{
   firstHalfLen=halfLen;
   secondHalfLen=halfLen;
}
for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen;
    firstHalfCOunter < firstHalfLen;
    firstHalfCOunter++)
{
  if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1)
  {
    count2+=1;
  }
  if(secondHalfCounter < arrayLength)
  {
    if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1)
    {
        count2+=1;
    }
    secondHalfCounter++; 
  }
}

Comparaison des performances (en utilisant timer.js) entre la longueur en cache pour la boucle VS la méthode ci-dessus.

http://jsfiddle.net/tejzpr/bbLgzxgo/

tejzpr
la source
0

Un autre test jsperf.com: http://jsperf.com/

La boucle inversée while semble être la plus rapide. Le seul problème est que (--i) s'arrêtera à 0. Comment puis-je accéder au tableau [0] dans ma boucle?

Moritz Schmitz c. Hülst
la source
2
Si vous le faites, while (i--)la véracité de isera testée avant de décrémenter plutôt que de décrémenter puis de tester la véracité.
Justin Fisher le
0

La boucle while est un peu plus rapide que la boucle.

var len = arr.length;
while (len--) {
    // blah blah
}

Utilisez la boucle while à la place

Azhar Zafar
la source
-1

La solution la plus élégante que je connaisse est d'utiliser la carte.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});
Dan
la source
46
La question n'est pas de demander la manière la plus lente d'itérer à travers une boucle
eoleary
-1

Essaye ça:

var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}
li bing zhao
la source
-1

Le moyen le plus rapide de boucler dans un tableau consiste à utiliser le filtre. La méthode filter () crée un nouveau tableau avec tous les éléments qui réussissent le test implémenté par la fonction fournie.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

const words = ['Floccinaucinihilipilification', 'limit', 'elite', 'Hippopotomonstrosesquipedaliophobia', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(new Date(), result);

D'après mon expérience, je préfère toujours les filtres, la carte etc.

Rigin Oommen
la source
La question concerne l'itération sur le tableau dans le plus court laps de temps possible sans copier le tableau dans un nouveau tableau.
Rahul Kadukar
-1

Depuis 2019, WebWorker est devenu plus populaire, pour les grands ensembles de données, nous pouvons utiliser WebWorker pour traiter beaucoup plus rapidement en utilisant pleinement des processeurs multicœurs.

Nous avons également Parallel.js qui rend WebWorker beaucoup plus facile à utiliser pour le traitement des données.

Stackia
la source