For-Schleife statt While-Schleife

Lesezeit: 6 Minuten

Benutzer-Avatar
Zufallsblau

Beim Durchlesen der jQuery-Quelle bin ich auf das folgende Stück Code gestoßen (verfügbar hier):

for (; i < length;) {
    if (callback.apply(object[i++], args) === false) {
        break;
    }
}

Warum ist ein for Schleife, die hier anstelle von a verwendet wird while Schleife?

  • Ich frage mich, ob dieser Code kürzer ist, wenn er minimiert wird? Es ist ein schrecklicher Code, und die jQuery-Jungs sind schlaue Leute, also würde ich denken, dass es für Minimierungszwecke ist.

    – Michael Stumm

    24. August 2011 um 0:20 Uhr

  • Durch das Entfernen aller Leerzeichen ist die Version von @aroth kürzer. Jeder Variablenname, der abgekürzt werden kann, wird gleich oft verwendet. Könnte noch kürzer werden. while(i<length&&callback.apply(object[i++],args)!==false);

    – Benutzer113716

    24. August 2011 um 0:33 Uhr

  • Man könnte argumentieren, dass das Ersetzen aller While-Schleifen durch diese Form von for im minimierten Code besser komprimiert. Keine Ahnung, ob sie das im Sinn hatten.

    – JB.

    24. August 2011 um 8:50 Uhr

Benutzer-Avatar
aroth

Ich stimme für jemanden, der eine Affinität zu schlechtem Programmierstil hat. Das ist die einzige Erklärung, die ich für beide sehen kann for Schleife und die i++ innerhalb eines Array-Index platziert werden. Ich denke das wäre besser:

while (i < length && callback.apply(object[i], args)) {
    i++;
}

Oder wenn Sie das Gefühl haben, dass die === Operator im ursprünglichen Beispiel hat Wert, dann:

while (i < length && callback.apply(object[i], args) !== false) {
    i++;
}

Ein weiterer möglicher Grund dafür könnte eine Leistungsoptimierung gewesen sein. Obwohl so schnell Benchmark die ich zusammengestellt habe, scheint diese Theorie zu widerlegen. Unter Windows die while Schleife oben ist 20 % schneller als das Original for Schleife in Chrome, in IE und Firefox führen beide Schleifen gleich aus. Unter OS X die for Schleife hat einen 10%igen Vorteil in Firefox, es gibt keinen Unterschied zwischen den beiden in Chrome, und Safari bevorzugt die while Schleife um 6%.

Aus Leistungssicht ist es also eine Wäsche. Wenn überhaupt, dann würden Sie nach Marktanteilen wahrscheinlich für Chrome unter Windows optimieren wollen, bevor Sie für Firefox auf Mac optimieren, in diesem Fall die while Schleife wäre wünschenswert.

Was mir sagt, dass es unwahrscheinlich ist, dass die Leistungsoptimierung bei diesem Code eine Rolle gespielt hat. Und ich kehre zu meiner ursprünglichen Theorie zurück, dass es nur ein Beispiel für einen schlechten Programmierstil ist, der den Code-Review-Prozess übersteht.

  • Das Strenge false Test ist notwendig, da das der ist eines Rückgabewert, der die Iteration unterbricht.

    – Benutzer113716

    24. August 2011 um 0:19 Uhr

  • Wäre ‘i’ in Ihrem Beispiel nicht um 1 out?

    – AnteSim

    24. August 2011 um 0:31 Uhr

  • Die zweite Version ist für die Äquivalenz zum Original in Fällen erforderlich, in denen der Rückruf zurückkehren könnte undefined oder 0. Die erste Version würde in diesen Fällen nicht identisch funktionieren.

    – jfriend00

    24. August 2011 um 0:41 Uhr


  • Dennoch ist der Code nicht äquivalent. Wenn die Schleife abbricht, weil der Callback falsch zurückgibt, i wird hier eins weniger sein als im ursprünglichen Code.

    – Jordi

    24. August 2011 um 15:26 Uhr


  • @Jordi – Der ursprüngliche Code kehrt zurück, nachdem die Schleife ausgeführt wurde, ohne einen zusätzlichen Verweis darauf zu machen iund i ist lokal auf die Funktion beschränkt. Sie sind also für alle praktischen Zwecke gleich. Es gibt in diesem Fall keinen Grund, sich um den Wert von zu kümmern i nachdem die Schleife beendet ist.

    – aroth

    24. August 2011 um 22:12 Uhr

Wahrscheinlich, weil es von a “umgestaltet” wurde for (x in obj) Schleife: http://james.padolsey.com/jquery/#v=1.3.2&fn=jQuery.each

Hier ist das Commit, das diese Kuriosität eingeführt hat.

Commit-Nachricht:

jquery-Kern: Codereduzierung bei $.each und $.curCSS.

Ausschnitt aus dem Diff:

-        for ( var i = 0, length = object.length; i < length; i++ )
-          if ( callback.apply( object[ i ], args ) === false )
+        for ( ; i < length; )
+          if ( callback.apply( object[ i++ ], args ) === false )

Es scheint, dass der Autor einfach die Gelegenheit verpasst hat, das zu ändern for in ein while.

Erstens fallen für die Verwendung von a nie Kosten an for Schleife über a while -Schleife, aber Sie erhalten zusätzliche Funktionalität mit der for Schleife, also verwenden einige Programmierer einfach immer die for:

for(;<condition>;){}
while(<condition>){}

Allerdings denke ich, dass der Zweck hier die Konsistenz mit dem umgebenden Code sein könnte.

Hier ist zum Beispiel ein Teil des ursprünglichen Codes. Wie Sie sehen können, können Sie in diesem Code die ganze Zeit im “for”-Schleifenmodus bleiben, also es fühlt sich konsistenter:

if (args) {
    if (isObj) {
        for (name in object) {
            if (callback.apply(object[name], args) === false) {
                break;
            }
        }
    } else {
        for (; i < length;) {
            if (callback.apply(object[i++], args) === false) {
                break;
            }
        }
    }
}

Vergleichen Sie dies mit dem Ersetzen der zweiten Schleife durch a while. Wenn Sie diesen Code lesen, müssen Sie von der Denkweise der “for”-Schleife in die Denkweise der “while”-Schleife wechseln. Jetzt weiß ich nicht, wie es Ihnen geht, aber ich finde es etwas schneller für meine Augen, zwischen den Schleifenbedingungen oben zu wechseln, im Gegensatz zu den Schleifenbedingungen unten. Dies liegt daran, dass ich mich im obigen Fall nur auf die Bedingungen konzentrieren kann, während mein Blick im unteren Fall darauf gerichtet ist, die Bedingungen erneut zu lesen while und die for jedes Mal, weil sie anders sind:

if (args) {
    if (isObj) {
        for (name in object) {
            if (callback.apply(object[name], args) === false) {
                break;
            }
        }
    } else {
        while (i < length) {
            if (callback.apply(object[i++], args) === false) {
                break;
            }
        }
    }
}

Ich habe festgestellt, dass solche Dinge auftreten, wenn ich Dinge umschreibe oder wenn mehrere Personen ein Stück Code berühren. Kann keinen besonderen Grund dafür erkennen.

Ich hoffe ich oberhalb dieses Blocks korrekt initialisiert wird.

Benutzer-Avatar
schäbunc

Die kürzeste und ehrlichste Antwort ist ziemlich kurz „einfach so“. Es gibt absolut keinen praktischen Grund dafür, wir gewinnen keinen Gewinn aus einer solchen 2-Lächeln-Schleife.

Wie aus den oben genannten Gründen, wie zum Beispiel:

  • Refactoring – was am ehesten möglich ist, aber dennoch keine Entschuldigung ist.
  • Minimierungsüberlegungen – was weniger, weniger möglich ist.
  • psychologische/Lesbarkeits-/codeunterstützende Probleme – Ich bezweifle sehr, dass jemand solchen Code schreibt, wenn man bedenkt, dass ein Benutzer für einige Codekonstruktionen verwirrt sein kann und die Konzentration verliert;

Nun, aus diesen Gründen – alle sind es definitiv wert, erwähnt zu werden, aber um ehrlich zu sein, ist der Codestil von JQuery nicht ideal. Manchmal da sind Gründe, warum es so ist, manchmal ist es nur eine Tatsache.

Produktionscode ist nicht immer der schönste Code. Das Lesen von produktionsreifem Hardcore-Code in jeder Sprache ist immer gut, aber es geht nicht zu 100 % um den Codestil. Sagen wir mal, vim ist schöne, sehr leistungsfähige Software, aber (was mich betrifft) kann mancher Purist mit seinem Quellcode überrascht sein. Obwohl Loops ok sind ))))

Benutzer-Avatar
Phineas

t wird also mindestens einmal ausgeführt, denn wenn Sie eine While-Schleife verwenden, wenn die Logik falsch ist, wird sie nicht ausgeführt. Für lopp wird es mindestens einmal ausgeführt, selbst wenn es falsch ist.

1282610cookie-checkFor-Schleife statt While-Schleife

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy