2010-05-10 16 views
14

Ich bin relativ neu in JS, so dass dies ein häufiges Problem sein kann, aber ich bemerkte etwas seltsam im Umgang mit For-Schleifen und Onclick-Funktion. Ich war in der Lage, das Problem mit diesem Code zu replizieren:JavaScript for Schleife Index Fremdheit

<html> 
<head> 

<script type="text/javascript"> 
window.onload = function() { 
    var buttons = document.getElementsByTagName('a'); 
    for (var i=0; i<2; i++) { 
     buttons[i].onclick = function() { 
      alert(i); 
      return false; 
     } 
    } 
} 

</script> 

</head> 

<body> 
<a href="">hi</a> 
<br /> 
<a href="">bye</a> 

</body> 

</html> 

Wenn die Links zu klicken, ich erwarten würde bekommen ‚0‘ und ‚1‘, sondern ich ‚2‘ für beide von ihnen. Warum ist das?

BTW, ich habe es geschafft, mein spezielles Problem zu lösen, indem ich das "this" -Schlüsselwort verwende, aber ich bin immer noch neugierig, was hinter diesem Verhalten steckt.

+0

Bitte zeigen Sie ein Beispiel, wie Sie das Problem mit "this" gelöst haben. –

Antwort

14

Sie haben a very common closure problem in der for Schleife.

In einem Closure enthaltene Variablen teilen sich die gleiche Umgebung. Wenn der Callback onclick ausgeführt wird, hat die Schleife ihren Verlauf durchlaufen und die Variable i wird auf den letzten Eintrag zeigen.

Sie können dieses Problem lösen mit noch mehr Schließungen, eine Funktion ab Werk mit:

function makeOnClickCallback(i) { 
    return function() { 
     alert(i); 
     return false; 
    }; 
} 

var i; 

for (i = 0; i < 2; i++) { 
    buttons[i].onclick = makeOnClickCallback(i); 
} 

Das ist ganz ein heikles Thema sein kann, wenn Sie nicht vertraut mit sind, wie Verschlüsse funktionieren. Sie können die folgenden Mozilla-Artikel für eine kurze Einführung überprüfen:


Hinweis: Ich würde auch vorschlagen nicht var innerhalb der for Schleife zu verwenden, da dies Sie Trick kann in der Annahme, dass die i Variable Block Umfang hat, wenn auf der anderen Seite die i Variable ist wie die buttons Variable, innerhalb der Funktion Bereich.

0

Es ist eine Reihenfolge der Ausführung Ausgabe

How to assign event callbacks iterating an array in javascript (jQuery)

Grundsätzlich ist die Click-Handler i gut, nachdem die Schleife greift wurde beendet, und deshalb i gleich 2.

+0

Es ist auch ein Problem Bereich, "ich" ist herumhängen, wenn es nicht offensichtlich ist, sollte es. – Greg

+0

Richtig, deshalb habe ich mich mit einem Post von mir über Schließungen verbunden. –

9

Sie müssen den Status der i -Variable speichern, da zum Zeitpunkt des Ereignisses der Bereichszustand i auf die maximale Schleifenanzahl gestiegen ist.

window.onload = function() { 
    var buttons = document.getElementsByTagName('a'); 
    for (var i=0; i<2; i++) { 
     (function (i) { 
      buttons[i].onclick = function() { 
       alert(i); 
       return false; 
      } 
     })(i); 
    } 
} 

Das obige Beispiel wird eine anonyme Funktion mit einem Argument i, die dann mit i wird geleitet, wie dieses Argument aufgerufen wird. Dadurch wird eine neue Variable in einem separaten Bereich erstellt, und der Wert wird zum Zeitpunkt der jeweiligen Iteration gespeichert.

+1

Das Erstellen von Funktionen in einer Schleife wird nicht empfohlen –

+0

@Ryan: Ich bin mir nicht sicher, ob das Pedanterie oder Verwirrung im Gespräch ist. Sie wiederholen eine JSLint/JSHint-Warnung, ohne sich die Zeit zu nehmen, um zu verstehen, was es bedeutet. Werfen Sie einen Blick auf die [Docs] (http: //www.jshint.com/docs/options/# loopfunc) für ein Beispiel einer Funktion, die nicht in einer Schleife erstellt werden sollte. IIFEs sind akzeptabel, weil es in einigen Szenarien so ziemlich die einzige Option ist, bis "let" universell unterstützt wird. Die akzeptierte Antwort erstellt auch Funktionen in Schleifen, aber keine Stimmen ablehnen oder dort kommentieren? –

+0

Okay, lassen Sie mich klarstellen: Sie erstellen * zwei * Funktionen in einer Schleife. Der IIFE und der Click-Handler. Die akzeptierte Antwort erstellt eine Funktion in einer Schleife: den Click-Handler. So minimiert die akzeptierte Antwort die Ineffizienzen, während Ihre maximiert sie. –

Verwandte Themen