Heim  >  Artikel  >  Web-Frontend  >  Eingehende Untersuchung der Effizienzprobleme und der damit verbundenen Optimierung von For-Schleifen in JavaScript_Javascript-Kenntnissen

Eingehende Untersuchung der Effizienzprobleme und der damit verbundenen Optimierung von For-Schleifen in JavaScript_Javascript-Kenntnissen

WBOY
WBOYOriginal
2016-05-16 15:10:521543Durchsuche

Underscore.js-Bibliothek

Wie viele Schleifen haben Sie an einem Tag (einer Woche) geschrieben?

var i;
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 doSomeWorkOn(someThing);
}

Es ist natürlich harmlos, aber es ist hässlich und seltsam und nicht wirklich etwas, worüber man sich beschweren könnte. Aber diese Schreibweise ist zu banal.

var i,
 j;
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 for(j = 0; j < someThing.stuff.length; j++) {
   doSomeWorkOn(someThing.stuff[j]);
 }
}

Sie erweitern fehlerhaften Code, und bevor Sie eine Menge Wenns werfen, sind Sie bereits verrückt.
Ich habe seit zwei Jahren keine Schleife mehr geschrieben.
„Wovon redest du?“
Es ist wahr, ein schlechter Witz. Eigentlich keine (ok, ich habe ein paar geschrieben), weil ich keine Schleifen schreibe und mein Code leichter zu verstehen ist.
Wie?

_.each(someArray, function(someThing) {
 doSomeWorkOn(someThing);
})

Oder noch besser:

_.each(someArray, doSomeWorkOn);

Das ist es, was underscorejs macht. Sauber, einfach, lesbar, kurz, keine Zwischenvariablen, keine Unmengen von Semikolons, einfach und sehr elegant.
Hier sind einige weitere Beispiele.

var i,
 result = [];
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 // 打到这,我已经手疼了
 if(someThing.isAwesome === true) {
   result.push(someArray[i]);
 }
}

Wieder ein typischer Anwendungsfall für die Zeitverschwendung durch Schleifen. Auch wenn diese Seiten Anti-Raucher und Vegetarismus fördern, bin ich empört, wenn ich diese Codes sehe. Schauen Sie sich die einfache Art an, es zu schreiben.

var result = _.filter(someArray, function(someThing) {
 return someThing.isAwesome === true;
})

Wie der Name des Filters im Unterstrich können Sie mit nur drei Codezeilen ein neues Array erstellen.
Oder möchten Sie diese Arrays in eine andere Form konvertieren?

var result = _.map(someArray, function(someThing) {
 return trasformTheThing(someThing);
})

Die oben genannten drei Beispiele reichen im täglichen Leben aus, aber diese Funktionen reichen nicht aus, um einen Unterstrich auf den Tisch zu legen.

var grandTotal = 0,
 somePercentage = 1.07,
 severalNumbers = [33, 54, 42],
 i; // don't forget to hoist those indices;
for(i = 0; i < severalNumbers.length; i++) {
 var aNumber = severalNumbers[i];
 grandTotal += aNumber * somePercentage;
}

Unterstrichversion

var somePercentage = 1.07,
 severalNumbers = [33, 54, 42],
 grandTotal;
grandTotal = _.reduce(severalNumbers, function(runningTotal, aNumber) {
 return runningTotal + (aNumber * somePercentage);
}, 0)

Das mag zunächst etwas seltsam erscheinen. Ich habe die Dokumentation zu Reduce überprüft und herausgefunden, dass es existiert. Da ich die Verwendung von Schleifen ablehne, ist es meine erste Wahl. Die oben genannten Dinge sind nur eine Einführung. Die UnderscoreJS-Bibliothek verfügt auch über viele tolle Funktionen.

30 Tage No-Use-Cycle-Challenge.

Verwenden Sie in den nächsten 30 Tagen keine Schleifen. Wenn Sie eine Menge unangenehmer und grober Dinge sehen, ersetzen Sie sie durch jede einzelne oder Karte. Etwas reduzierender verwenden.

Sie müssen beachten, dass Underscore das Tor zur funktionalen Programmierung ist. Ein sichtbarer, unsichtbarer Weg. Ein guter Weg.


OurJS-Hinweis* Moderne Browser unterstützen derzeit die Methoden „Every“, „Filter“, „Mapping“ und „Reduction“, aber die Underscore-Bibliothek kann Kompatibilität mit älteren Versionen von IE erreichen. Das Folgende ist ein Beispiel, das mit nativen ES5-Methoden geschrieben wurde:

[3,4,5,3,3].forEach(function(obj){
  console.log(obj);
});

[1,2,3,4,5].filter(function(obj){
  return obj < 3
});

[9,8,5,2,3,4,5].map(function(obj){
  return obj + 2;
});

[1,2,3,4,5].reduce(function(pre, cur, idx, arr) {
  console.log(idx);  //4 个循环: 2-5
  return pre + cur;
});  //15

//sort方法同样很有用
[9,8,5,2,3,4,5].sort(function(obj1, obj2){
  return obj1 - obj2;
});

for in und for-Schleife

Jemand hat darauf hingewiesen, dass die Effizienz von for in viel geringer ist als die von for-Schleifen. Lassen Sie uns nun die Effizienz der Verwendung von for in, for loop und forEach in verschiedenen Browsern bei der Verarbeitung großer Arrays testen.

Derzeit speichert die meiste Open-Source-Software die Array-Länge in der for-Schleife zwischen, da die allgemeine Ansicht darin besteht, dass einige Browser Array.length die Array-Länge jedes Mal neu berechnen, sodass zum Speichern der Array-Länge normalerweise temporäre Variablen verwendet werden im Voraus, wie zum Beispiel:

for (var idx = 0, len = testArray.length; idx < len; idx++) {
 //do sth.
}

Wir werden auch den Leistungsunterschied zwischen Caching und keinem Caching testen.

Fügen Sie außerdem in jeder Testschleife eine Summationsoperation hinzu, um zu zeigen, dass es sich nicht um eine leere Schleife handelt.

for (var idx = 0, len = testArray.length; idx < len; idx++) {
 //do sth.
}

Wir werden auch den Leistungsunterschied zwischen Caching und keinem Caching testen.

Fügen Sie außerdem in jeder Testschleife eine Summationsoperation hinzu, um zu zeigen, dass es sich nicht um eine leere Schleife handelt.

Der Testcode lautet wie folgt. Klicken Sie zum Anzeigen auf „Ausführen“
HTML-Code

<h4 id="browser"></h4>
<table id="results" class="table"></table>

JavaScript-Code

function () {

 //准备测试数据, 有200万条数据的大数组
 var testArray = []
  , testObject = {}
  , idx
  , len = 2000000
  , tmp = 0
  , $results = $("#results")
  , $browser = $("#browser")
  ;

 $browser.html(navigator.userAgent);
 $results.html('');

 for (var i = 0; i < len; i++) {
  var number = Math.random(); //若希望加快运算速度可使用取整:Math.random() * 10 | 0
  testArray.push(number);
  testObject[i] = number;
 }

 $results.append('<tr><th>测试代码</th><th>计算结果</th><th>所需时间,毫秒</th></tr>');

 //测试函数
 var test = function(testFunc) {
  var startTime
   , endTime
   , result
   ;

  startTime = new Date();
  tmp = 0;
  testFunc();
  endTime  = new Date();

  //计算测试用例(Test Case)运行所需要的时间
  result = endTime - startTime;
  $results.append('<tr><td><pre class="brush:php;toolbar:false">{0}
{1}{2}'.format(testFunc.toString(), tmp | 0, result)); }; test(function() { //测试for in 的效率 for (idx in testArray) { tmp += testArray[idx]; //经测试,idx是string类型,可能是慢的原因之一 } }); test(function() { //测试for loop循环的效率 for (idx = 0, len = testArray.length; idx < len; idx++) { tmp += testArray[idx]; } }); test(function() { //测试forEach的效率 testArray.forEach(function(data) { tmp += data; }); }); test(function() { //测试不缓存Array.length时效率 for (idx = 0; idx < testArray.length; idx++) { tmp += testArray[idx]; } }); test(function() { //测试使用{} (Object) 存健值对时,使用for in的效率如何 for (idx in testObject) { tmp += testObject[idx]; } }); test(function() { //测试从{} Object查值时的效率如何(这里的健key值事先己知) for (idx = 0, len = testArray.length; idx < len; idx++) { tmp += testObject[idx]; } }); }

Führen Sie [Bitte warten Sie einen Moment] aus
Testergebnisse
Die Testergebnisse können je nach Berechnung variieren. Dies ist eine Zusammenfassung der Testergebnisse von Firefox, Chrome und IE, die auf meinem Computer ausgeführt werden.

2016313110044207.jpg (971×678)

Im Folgenden sind einige beobachtete Schlussfolgerungen aufgeführt

  • For in ist viel langsamer als die for-Schleife, mindestens 20-mal langsamer in Chrome
  • FF wurde forEach (ES5) optimiert und seine Leistung ist besser als die for-Schleife, aber die Leistung von Chrome/IEn ist schlecht
  • Das Caching von Array.length durch FF/Chrome ist etwas langsamer als die direkte Verwendung. Mit Ausnahme der neuesten Version von IE ist die Leistungsverbesserung minimal (das ist sehr unerwartet)
  • In einigen Fällen scheint die Leistung des JS-Motors von FF besser zu sein als die des V8
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn