Was ist der schnellste Weg, um ein Array in JavaScript zu durchlaufen?

248

Ich habe aus Büchern gelernt, dass man so eine Schleife schreiben sollte:

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

Das arr.lengthwird also nicht jedes Mal berechnet.

Andere sagen, dass der Compiler dies optimieren wird, sodass Sie einfach schreiben können:

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

Ich möchte nur wissen, welcher Weg in der Praxis der beste ist.

wong2
quelle
1
auch einen Blick wert, wenn es um Array-Looping geht: jsperf.com/array-loop-var-caching
cloakedninjas
@ wong2 Dieser Benchmark von Browserdiet bietet eine umfassendere Sammlung von Alternativen.
Domi
1
jsben.ch/#/y3SpC
EscapeNetscape
Verbessert gegenüber dem vorherigen jsben: jsben.ch/#/R6LbS
Corbfon
Können wir die for ... ofSchleife in diesen Wettbewerb einführen ? Die Syntax scheint noch einfacher zu sein als eine for-Schleife ohne Caching, und ich möchte wissen, ob ich zur Verwendung von for of-Schleifen wechseln soll.
ProgrammiererRaj

Antworten:

339

Nach diesem Test mit den meisten modernen Browsern ...

http://jsben.ch/dyM52

Derzeit die schnellste Form der Schleife (und meiner Meinung nach die syntaktisch offensichtlichste).

Ein Standard für Schleifen mit Längen-Caching

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

}

Ich würde sagen, dass dies definitiv ein Fall ist, in dem ich Entwickler von JavaScript-Engines begrüße. Eine Laufzeit sollte aus Gründen der Klarheit und nicht der Klugheit optimiert werden .

jondavidjohn
quelle
6
Interessanterweise ist dies in IE9 schneller: für (var i = 0, len = myArray.length; i <len; ++ i) {} // Präfix inkr, anstelle von Postfix
Christopher Bennage
4
Siehe Antwort Präfix - Operatoren über postfix aus anderen Gründen zu verwenden ++i.
Bennett McElwee
4
Ich habe mit dem Präfix-Operator getestet, wie @BennettMcElwee vorgeschlagen hat, und er läuft etwas schneller: for(var i=0, len=myArray.length; i<len; ++i) Überprüfen Sie jsperf.com/caching-array-length/84
victmo
21
Sie müssen vorsichtig sein, wenn Sie diese Schleife verwenden. Ich fing an, es zu benutzen und hatte aufgrund eines Fehlers, den ich gemacht hatte, einen schwer zu verfolgenden Fehler. Wenn Sie zwei Schleifen wie folgt verschachteln : jsfiddle.net/KQwmL/1 . Sie müssen darauf achten, die Variable in den beiden Schleifen unterschiedlich zu benennen, da sonst die zweite Schleife die erste Länge überschreibt.
Rui Marques
6
@WillshawMedia Sie können mehrere Variablen mit einer einzigen varAnweisung deklarieren . Wie es geschrieben steht, lenist tatsächlich so, wie Sie es vorschlagen.
Jondavidjohn
90

Der absolut schnellste Weg, um ein Javascript-Array zu durchlaufen, ist:

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

Einen vollständigen Vergleich finden Sie unter http://blogs.oracle.com/greimer/entry/best_way_to_code_a

gnur
quelle
1
Vergessen Sie nicht zu verwenden var(sonst lenwird eine globale Variable). Weitere Loop-Benchmarks finden Sie unter jsperf.com/loops .
Mathias Bynens
22
Der Blog-Beitrag, auf dem diese Antwort basiert, ist jetzt fast 4 Jahre alt, und in js-Motoren hat sich in dieser Zeit viel geändert. Einen aktualisierten Vergleich finden Sie in meiner Antwort unten.
Jondavidjohn
1
Ich stimme @jondavidjohn zu. Ich habe diesen Code getestet und es stellte sich heraus, dass er weniger effizient ist ... Überprüfen Sie jsperf.com/caching-array-length/84
victmo
Die obige Antwort ist fast universell (über alle Browser hinweg) viel langsamer als eine for-Schleife. Siehe den JSPerf-Link in der akzeptierten Antwort. Es ist eine große Schande, denn es ist IMO extrem lesbar.
Letharion
3
Ich vermute @jondavidjohn, dass du mit "meine Antwort unten" "meine Antwort oben" meinst lol.
Shanimal
40

Ab Juni 2016 werden einige Tests in neuestem Chrome durchgeführt (71% des Browsermarktes im Mai 2016 und mehr):

  • Die schnellste Schleife ist eine for-Schleife , sowohl mit als auch ohne Caching-Länge, die eine wirklich ähnliche Leistung liefert. (Die for-Schleife mit zwischengespeicherter Länge lieferte manchmal bessere Ergebnisse als die ohne Caching, aber der Unterschied ist nahezu vernachlässigbar, was bedeutet, dass die Engine möglicherweise bereits für den Standard optimiert ist und wahrscheinlich am einfachsten für eine Schleife ohne Caching ist.)
  • Die while-Schleife mit Dekrementen war ungefähr 1,5-mal langsamer als die for-Schleife.
  • Eine Schleife, die eine Rückruffunktion verwendet (wie der Standard für jede), war ungefähr zehnmal langsamer als die for-Schleife.

Ich glaube, dieser Thread ist zu alt und es ist irreführend, wenn Programmierer glauben, sie müssten die Länge zwischenspeichern oder Reverse-Traversing mit Dekrementen verwenden, um eine bessere Leistung zu erzielen. Sie schreiben Code, der weniger lesbar und fehleranfälliger ist als eine einfache unkomplizierte for-Schleife. Daher empfehle ich:

  • Wenn Ihre App viele Elemente durchläuft oder sich Ihr Schleifencode in einer häufig verwendeten Funktion befindet, ist eine einfache for-Schleife die Antwort:

    for (var i = 0; i < arr.length; i++) {
      // Do stuff with arr[i] or i
    }
    
  • Wenn Ihre App nicht wirklich viele Elemente durchläuft oder Sie hier und da nur kleine Iterationen durchführen müssen, ist die Verwendung des Standard-forEach-Rückrufs oder einer ähnlichen Funktion aus der JS-Bibliothek Ihrer Wahl möglicherweise verständlicher und weniger fehleranfällig, da Der Bereich der Indexvariablen ist geschlossen und Sie müssen keine Klammern verwenden, um direkt auf den Array-Wert zuzugreifen:

    arr.forEach(function(value, index) {
      // Do stuff with value or index
    });
    
  • Wenn Sie wirklich ein paar Millisekunden kratzen müssen, während Sie über Milliarden von Zeilen iterieren, und sich die Länge Ihres Arrays während des Vorgangs nicht ändert, können Sie die Länge in Ihrer for-Schleife zwischenspeichern. Obwohl ich denke, dass dies heutzutage wirklich nicht notwendig ist:

    for (var i = 0, len = arr.length; i < len; i++) {
      // Do stuff with arr[i]
    }
    
CGodo
quelle
Nee. jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 zeigt, dass die schnellste "Umkehrschleife, impliziter Vergleich, Inline-Code" (105.221 Operationen / Sek.) ist, während "Schleife, zwischengespeicherter Wert, Inline-Code" nur 76.635 Operationen / Sek. erzielte (Chrome 38.0.2125.111) )
Fr0sT
@ Fr0sT Ihr Benchmark ist ein anderes Szenario, bei dem Arrays von Index 1 bis <= Länge durchlaufen werden. Dies wird natürlich zu unterschiedlichen Ergebnissen führen. Wenn Sie versuchen, nullbasierte Arrays mit <Länge zu durchlaufen - was meiner Meinung nach das übliche Szenario ist -, werden Sie feststellen, dass die Ergebnisse mit einer normalen "for" -Schleife besser optimiert werden (wobei die zwischengespeicherte Länge etwas schneller ist).
CGodo
Kyopaxa hat die Benchmarks auf (0 <= i <Länge) geändert, die Ergebnisse sind gleich. "Umkehrschleife, impliziter Vergleich, Funktionsaufruf" erzielte 365 kops / s, während "Schleife, zwischengespeicherter Wert, inline Code" 350 kops / s (FF 51) erzielte
Fr0sT
@ Fr0sT, wenn Sie die auf Null basierenden zwischengespeicherten for-Schleifen ohne gleichen Vergleich ändern, z. B. for(let i=0, j=array.length; i < j; i++)die Vorwärtsbewegung für Schleifen erheblich beschleunigen. Bei einigen Tests habe ich gewonnen, bei den meisten lag es innerhalb der Fehlergrenze oder der Rückwärtsschleife.
Isaac B
1
@IsaacB und alle, sorry, ich habe nicht bemerkt, dass die Bank ganz falsch ist - alle direkten Schleifen iterieren 1..Länge, während umgekehrte Schleifen die Länge..0 iterieren (arr [Länge] Element ist ungültig). Ich habe die Tests korrigiert und jetzt zeigen sie die folgenden Ergebnisse: "Schleife, Inline-Code" 360.616 Operationen / Sek. ± 0,27%, "Schleife, zwischengespeicherter Wert, Inline-Code" 345.786 Operationen / Sek. ± 2,18% (Sic!) "Umkehrschleife, impliziter Vergleich, Inline-Code "322.640 Operationen / Sek. ± 2,90% (!!!). Die Tests wurden von FF51 durchgeführt. Neue Bank ist hier jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570 . Es scheint also keinen Sinn zu haben, die Schleifen zu hässlich zu machen.
Fr0sT
31

Wenn die Reihenfolge nicht wichtig ist, bevorzuge ich diesen Stil:

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

Es speichert die Länge zwischen und ist viel kürzer zu schreiben. Es wird jedoch in umgekehrter Reihenfolge über das Array iteriert.

Felix Kling
quelle
6
Du hast es gerade getötet.
Vignesh Raja
brauchst du nicht i> = 0;?
MarwaAhmad
3
@MarwaAhmad: Nein. Gibt i--eine Nummer zurück und sobald die Nummer ist, liegt 0die Bedingung falsedaran Boolean(0) === false.
Felix Kling
30

Es ist erst 2018, also könnte ein Update schön sein ...

Und ich muss der akzeptierten Antwort wirklich widersprechen . Es wird in verschiedenen Browsern verschoben. Einige arbeiten forEachschneller, andere schneller, for-loopund andere sind while hier ein Benchmark für alle Methoden http://jsben.ch/mW36e

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

und da Sie eine Menge for-Schleifen sehen können for(a = 0; ... ), ist es erwähnenswert, dass ohne 'var' Variablen global definiert werden und dies die Geschwindigkeit dramatisch beeinflussen kann, so dass es langsam wird.

Duffs Gerät läuft in der Oper schneller, aber nicht in 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
quelle
3
@ Maykonn wollten Sie wahrscheinlich sagen "und es funktioniert überall außer Opera Mini"
Dube
3
@Maykonn Dies ist in der Standardansicht nicht aufgeführt, da 0,18% aller Benutzer über IE8 verfügen und Sie keine Zeit damit verschwenden sollten, es zu unterstützen. 2018 ist es ein totes Pferd.
Dube
1
Es ist definitiv wahr, wenn Sie alle Benutzer auf der ganzen Welt berücksichtigen. Leider ist IE8 in bestimmten Teilen der Welt noch relevant.
Maykonn
1
Wenn ich darf, haben nicht nur verschiedene Browser unterschiedliche Ergebnisse mit unterschiedlichen Methoden, sondern dieselben Browser haben unterschiedliche Ergebnisse mit unterschiedlichen Eingaben. Ein großes Array nur mit Zahlen wird sehr optimiert, ein kleines gemischtes Array hingegen nicht.
Kaiido
1
@ Tahlil Danke.
nullqube
19

2014 Whileist zurück

Denken Sie einfach logisch.

Schau dir das an

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

 //do stuff

}
  1. Es müssen mindestens 2 Variablen (Index, Länge) erstellt werden.
  2. Sie müssen überprüfen, ob der Index kleiner als die Länge ist
  3. Der Index muss erhöht werden
  4. Die forSchleife hat 3 Parameter

Sagen Sie mir jetzt, warum dies schneller sein sollte als:

var length = array.length;

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

 //do stuff

}
  1. Eine Variable
  2. Keine Schecks
  3. der Index wird verringert (Maschinen bevorzugen das)
  4. while hat nur einen Parameter

Ich war total verwirrt, als Chrome 28 zeigte, dass die for-Schleife schneller ist als die Weile. Das muss irgendwie ben gewesen sein

"Äh, jeder benutzt die for-Schleife. Konzentrieren wir uns darauf, wenn wir für Chrome entwickeln."

Aber jetzt, im Jahr 2014, ist die while-Schleife wieder auf Chrom. es ist 2 mal schneller, in anderen / älteren Browsern war es immer schneller.

In letzter Zeit habe ich einige neue Tests gemacht. In der realen Welt sind diese Funktionscodes nichts wert und jsperf kann die while-Schleife nicht richtig ausführen, da die array.length neu erstellt werden muss, was ebenfalls Zeit kostet.

Sie können nicht die tatsächliche Geschwindigkeit einer while-Schleife auf jsperf erhalten.

Sie müssen Ihre eigene benutzerdefinierte Funktion erstellen und dies mit überprüfen window.performance.now()

Und ja ... die while-Schleife ist auf keinen Fall einfach schneller.

Das eigentliche Problem ist eigentlich die Dom-Manipulation / Renderzeit / Zeichenzeit oder wie auch immer Sie es nennen möchten.

Zum Beispiel habe ich eine Canvas-Szene, in der ich die Koordinaten und Kollisionen berechnen muss ... dies geschieht zwischen 10 und 200 Mikrosekunden (nicht Millisekunden). Es dauert tatsächlich verschiedene Millisekunden, um alles zu rendern. Wie in DOM.

ABER

Es gibt eine andere super performante Möglichkeit, loopin einigen Fällen das for zu verwenden, um beispielsweise ein Array zu kopieren / klonen

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

Beachten Sie die Einrichtung der Parameter:

  1. Wie in der while-Schleife verwende ich nur eine Variable
  2. Sie müssen überprüfen, ob der Index größer als 0 ist.
  3. Wie Sie sehen können, unterscheidet sich dieser Ansatz von der normalen for-Schleife, die jeder verwendet, da ich Dinge innerhalb des 3. Parameters mache und auch direkt innerhalb des Arrays abnehme.

Dies bestätigt, dass Maschinen wie die -

Schreiben, dass ich dachte, es ein wenig kürzer zu machen und einige nutzlose Sachen zu entfernen, und schrieb dieses mit dem gleichen Stil:

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

Selbst wenn es kürzer ist, sieht es so aus, als würde ieine weitere Verwendung alles verlangsamen. Es ist 1/5 langsamer als die vorherige forund die vorherige Schleife while.

Hinweis: Das ;ist sehr wichtig nach dem für looo ohne{}

Auch wenn ich Ihnen gerade gesagt habe, dass jsperf nicht der beste Weg ist, um Skripte zu testen. Ich habe diese 2 Schleifen hier hinzugefügt

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

Und hier ist eine weitere Antwort zur Leistung in Javascript

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

Diese Antwort soll performante Möglichkeiten zum Schreiben von Javascript aufzeigen. Wenn Sie das nicht lesen können, fragen Sie und Sie erhalten eine Antwort oder lesen ein Buch über Javascript http://www.ecma-international.org/ecma-262/5.1/

cocco
quelle
Diese Antwort beginnt sehr gut . Mir ist aufgefallen, dass die letzten paar Jahre forschneller waren als die while, und ich habe einmal auf crome-dev gelesen, dass es genau aus dem Grund war, den Sie erwähnen. Es wäre nur eine Frage der Zeit while, bis sie wieder aufholen würden. Von diesem Punkt an, die Logik in dem ersten Teil Ihrer Antwort halten wird (wieder einmal, yay!) Moderne Implementierungen folgen jedoch nicht mehr starr jedem von Ecma festgelegten Schritt (sie optimieren). Da Ihr Motor jetzt nicht mehr der auffälligste Flaschenhals ist, kann man jetzt tatsächlich die CPU-Cache-Fehler in Rückwärtsschleifen feststellen !
GitaarLAB
Erklären Sie, vielleicht kann ich die Antwort korrigieren oder etwas Neues lernen. btw die Antwort ist jetzt mehr als ein Jahr alt ... Browser im Laufe der Zeit verändert haben , wie sie es immer tun ...
Cocco
Meiner Meinung nach ist while (--length) böse, weil es zwar technisch funktioniert, weil 0 falsch ist, 0 und false semantisch gesehen jedoch nicht wirklich dasselbe sind.
Scott.korin
Ja ... es ist jetzt ein älterer Beitrag ... aber ja, ich liebe die Einfachheit der Zeit. Und sicher, wie Sie es in beiden Fällen erwähnen, müssen Sie wissen, was zu schreiben ist. Auf der anderen Seite hatte ich nie die Notwendigkeit, negative Zahlen zu durchlaufen.
Cocco
9
"Maschinen bevorzugen dies" klingt wie ein Satz aus einer Anzeige für ein Waschmittel
CocoaBean
11

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

Die letzte Testversion, die ich vorbereitet habe (indem ich eine ältere wiederverwendete), zeigt eines.

Die Caching-Länge ist nicht so wichtig, schadet aber nicht.

Jeder erste Testlauf, der oben verlinkt ist (auf der frisch geöffneten Registerkarte), liefert die besten Ergebnisse für die letzten 4 Snippets (3., 5., 7. und 10. in Diagrammen) in Chrome, Opera und Firefox in meinem Debian Squeeze 64-Bit ( meiner Desktop-Hardware) ). Nachfolgende Läufe ergeben ein ganz anderes Ergebnis.

Leistungsbezogene Schlussfolgerungen sind einfach:

  • Gehen Sie mit for-Schleife (vorwärts) und testen Sie mit !==anstelle von <.
  • Wenn Sie das Array später nicht wiederverwenden müssen, ist die while-Schleife mit dekrementierter Länge und destruktivem shift()Array ebenfalls effizient.

tl; dr

Heutzutage (2011.10) scheint das folgende Muster das schnellste zu sein.

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

Beachten Sie, dass das Caching arr.lengthhier nicht entscheidend ist. Sie können also nur testen, ob die i !== arr.lengthLeistung sinkt, aber Sie erhalten kürzeren Code.


PS: Ich weiß, dass ein Snippet mit shift()seinem Ergebnis verwendet werden kann, anstatt auf das 0. Element zuzugreifen, aber ich habe das irgendwie übersehen, nachdem ich die vorherige Revision (die falsche while-Schleifen hatte) wiederverwendet habe, und später wollte ich die bereits erhaltenen Ergebnisse nicht verlieren.

przemoc
quelle
Das Erstellen einer Variablen in der Schleife wie let current = arr [i] kann eine Leistung reduzieren (große Speicherzuweisung)? Oder wäre es besser, den Strom vor der Schleife zu deklarieren? Oder verwenden Sie arr [i] an allen Stellen innerhalb der Schleife?
Makarov Sergey
8

"Best" wie bei reiner Leistung? oder Leistung UND Lesbarkeit?

Reine Leistung "am besten" ist dies, die einen Cache und den ++ Präfixoperator verwendet (meine Daten: http://jsperf.com/caching-array-length/189 )

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

Ich würde argumentieren, dass die for-Schleife ohne Cache das beste Gleichgewicht zwischen Ausführungszeit und Lesezeit des Programmierers darstellt. Jeder Programmierer, der mit C / C ++ / Java gestartet ist, verschwendet keine ms, um diese durchzulesen

for(var i=0; i < arr.length; i++){
  // blah blah
}
Valbaca
quelle
2
+1 zur besseren Lesbarkeit. Egal wie gut der lenName ist, man müsste immer eine doppelte Aufnahme dieser ersten Schleife machen. Die Absicht der zweiten Schleife ist offensichtlich.
Josh Johnson
7

** Cache die Array-Länge innerhalb der Schleife, einige Sekunden Zeit werden verstrichen. Abhängig von den Elementen im Array, wenn mehr Elemente im Array vorhanden sind, gibt es einen großen Unterschied in Bezug auf Ms der Zeit *

** **.

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
quelle
6

Dies scheint bei weitem der schnellste Weg zu sein ...

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

Berücksichtigen Sie, dass dies das Array verbraucht, es isst und nichts mehr übrig lässt ...

Sergio
quelle
2
arr.shift();Stattdessen arr.pop() kann eine Array-Umkehrung vermieden werden.
Tintu C Raju
1
@Gargaroz, wenn Sie einen JSON von einem Webservice erhalten, z. B. einen Chat-Service oder Artikel in einem Produktkatalog. Eine andere Situation, in der Sie das Array nur einmal verwenden müssen, kann beispielsweise ein Diagramm sein, das auf Intervallbasis viele Koordinaten erhält. Es gibt viele Beispiele.
Sergio
Cool, danke für die Erklärung, sehr nett von dir; Können Sie mir die Richtung zeigen, in der ich weitere Beispiele finden kann, um diese Art von Schleife auszunutzen?
Gargaroz
1
Derzeit in Chrome 53 und Firefox 48 ist es einer der langsamsten Ansatz - überprüfen Sie auf perfjs.info/array-iteration
Pencroff
1
@ Alireza stimme zu, ich habe auch einen Kommentar dazu in meiner Antwort.
Sergio
4

Es ist das Jahr 2017 .

Ich habe einige Tests gemacht.

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

Die whileMethode scheint in Chrome die schnellste zu sein.

Sieht aus wie die linke Abnahme ( --i) ist viel schneller als die andere ( ++i, i--, i++) auf Firefox.

Dieser Ansatz ist der Fasten im Durchschnitt. Das Array wird jedoch in umgekehrter Reihenfolge wiederholt.

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

Wenn die Vorwärtsreihenfolge wichtig ist, verwenden Sie diesen Ansatz.

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}
SeregPie
quelle
3
Mit dem Schlüsselwort vergleichen letSie tatsächlich die Leistung der Bereichserstellung anstelle der Schleifenleistung. Durch die Verwendung let i = 0, ii = array.lengthin Ihren forSchleifen wird ein neuer Bereich für diese Variablen innerhalb des forBlocks erstellt. Ihre whileBeispiele erstellen keinen neuen Bereich für die Variablen innerhalb des whileBlocks und sind daher schneller. Wenn Sie varanstelle von letfor-Schleifen verwenden, werden Sie sehen, dass for-Schleifen 2017 immer noch so schnell wie whiles sind, aber besser lesbar.
CGodo
Hier ist ein jsperf von dem, wovon ich spreche: jsperf.com/javascript-loop-testing-let-vs-var
CGodo
Dies ist nur ein Problem in Chrome. In anderen Browsern varund lethaben die gleiche Leistung - stackoverflow.com/a/32345435/1785975
SeregPie
Interessant. Wie auch immer, ich finde die Aussage " whilein Chrome schneller sein" nicht richtig. Dies ist nur bei Verwendung letaufgrund von Leistungsproblemen dieses Keywords in Chrome möglich. Wenn Sie varoder mit anderen Browsern verwenden forund whileziemlich gleich sind, forist dies je nach Benchmark manchmal sogar noch schneller und imho kompakter und lesbarer.
CGodo
2

Ich schreibe immer im ersten Stil.

Auch wenn ein Compiler intelligent genug ist, um ihn für Arrays zu optimieren, aber dennoch intelligent, wenn wir hier DOMNodeList oder ein kompliziertes Objekt mit berechneter Länge verwenden?

Ich weiß, was die Frage über Arrays ist, aber ich denke, es ist eine gute Praxis, alle Ihre Loops in einem Stil zu schreiben.

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

i ++ ist schneller als ++ i, --i und i--

Sie können auch die letzte Zeile speichern, die arr [i ++] ausführt, wenn Sie das letzte Mal auf i zugreifen müssen (dies kann jedoch schwierig zu debuggen sein).

Sie können es hier testen (mit anderen Schleifentests): http://jsperf.com/for-vs-whilepop/5

Forestrf
quelle
1
Derzeit in Chrome 53 ist es wahr, aber Firefox 48 hat die gleiche Geschwindigkeit - überprüfen Sie auf perfjs.info/array-iteration
Pencroff
thunderguy.com/semicolon/2002/08/13/… sagt ++iist schneller ...
IMTheNachoMan
1

Ab September 2017 zeigen diese jsperf-Tests, dass das folgende Muster unter Chrome 60 am leistungsfähigsten ist:

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

Kann sich jemand reproduzieren?

John Vandivier
quelle
Ja, es scheint am schnellsten zu sein. Versuchen Sie jedoch, dies in IE11 auszuführen, und diese Optionen sind die langsamsten. Und in Firefox 55.03 erreicht der 'alte kaputte zwischengespeicherte Len' 12 mil, eine erstaunliche Leistung im Vergleich zu 3,3 k Chrom. Um in allen Browsern eine gleichbleibende Leistung zu erzielen, sollten Sie für jeden Browser die schnellste Durchschnittsschleife verwenden.
Plippie
0

Ich habe einige andere Möglichkeiten ausprobiert, um ein großes Array zu iterieren, und festgestellt, dass das Halbieren der Array-Länge und das anschließende Iterieren beider Hälften in einer einzigen Schleife schneller ist. Dieser Leistungsunterschied kann bei der Verarbeitung großer Arrays festgestellt werden .

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++; 
  }
}

Einige Leistungsvergleiche (unter Verwendung von timer.js) zwischen der for-Schleife mit zwischengespeicherter Länge und der obigen Methode.

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

tejzpr
quelle
0

Ein weiterer jsperf.com-Test: http://jsperf.com/while-reverse-vs-for-cached-length

Die umgekehrte while-Schleife scheint die schnellste zu sein. Das einzige Problem ist, dass while (--i) bei 0 stoppt. Wie kann ich dann in meiner Schleife auf Array [0] zugreifen?

Moritz Schmitz v. Hülst
quelle
2
Wenn Sie dies tun, while (i--)wird die Wahrhaftigkeit von ivor dem Dekrementieren geprüft, anstatt zu dekrementieren und dann die Wahrhaftigkeit zu testen.
Justin Fisher
0

While-Schleife ist etwas schneller als for-Schleife.

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

Verwenden Sie stattdessen die while-Schleife

Azhar Zafar
quelle
-1

Die eleganteste Lösung, die ich kenne, ist die Verwendung einer Karte.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});
Dan
quelle
46
Die Frage ist nicht nach dem langsamsten Weg, um durch eine Schleife zu iterieren
eoleary
-1

Versuche dies:

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

Der schnellere Weg, ein Array zu schleifen, ist die Verwendung des Filters. Die filter () -Methode erstellt ein neues Array mit allen Elementen, die den von der bereitgestellten Funktion implementierten Test bestehen.

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

Aus meiner Erfahrung bevorzuge ich immer Filter, Karten usw.

Rigin Oommen
quelle
Die Frage besteht darin, das Array in kürzester Zeit zu durchlaufen und das Array nicht in ein neues Array zu kopieren.
Rahul Kadukar
-1

Ab 2019 ist WebWorker beliebter geworden. Bei großen Datenmengen können wir WebWorker verwenden, um durch die vollständige Nutzung von Multi-Core-Prozessoren viel schneller zu verarbeiten.

Wir haben auch Parallel.js, die die Verwendung von WebWorker für die Datenverarbeitung erheblich vereinfachen.

Stackia
quelle