Frage

    

Diese Frage bereits eine Antwort hier:

         

Hier ist eine vereinfachte Version von etwas, das ich zu laufen bin versucht:

for (var i = 0; i < results.length; i++) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
        change_selection(i);
    }); 
}

, aber ich finde, dass jeder Zuhörer den Wert von results.length verwendet (den Wert, wenn der für die Schleife beendet). Wie kann ich Listener hinzufügen, so dass jeder den Wert von i verwendet zu der Zeit ich es hinzufügen, anstatt die Bezugnahme auf i?

War es hilfreich?

Lösung

In modernen Browsern können Sie die let oder const Schlüsselwörter verwenden, um eine Block-Bereichs-Variablen zu erstellen:

for (let i = 0; i < results.length; i++) {
  let marker = results[i];
  google.maps.event.addListener(marker, 'click', () => change_selection(i));
}

In älteren Browsern, benötigen Sie einen separaten Bereich zu erstellen, den die Variable in seinem aktuellen Zustand spart, indem es als Funktionsparameter übergeben:

for (var i = 0; i < results.length; i++) {
  (function (i) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
      change_selection(i);
    }); 
  })(i);
}

Durch eine anonyme Funktion erstellen und mit den Variablen als erstes Argument aufrufen, Sie vorbei-by-Wert an die Funktion und einen Verschluss zu schaffen.

Andere Tipps

Neben den Schließungen, können Sie function.bind verwenden:

google.maps.event.addListener(marker, 'click', change_selection.bind(null, i));

übergibt den Wert von i in als Argument an die Funktion, wenn sie aufgerufen. (null ist für die Bindung this, die Sie in diesem Fall nicht brauchen.)

function.bind wurde durch den Prototyp Rahmen eingeführt und hat sich in ECMAScript Fifth Edition standardisiert. Bis Browser alle Unterstützung, die es nativ, können Sie Ihre eigene function.bind Unterstützung mit Schließungen hinzufügen:

if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}

Verschlüsse:

for (var i = 0, l= results.length; i < l; i++) {
    marker = results[i];
    (function(index){
        google.maps.event.addListener(marker, 'click', function() { 
            change_selection(index);
        }); 
    })(i);
}

EDIT, 2013: Diese werden jetzt allgemein als ein IIFE

Sie Wicklung mit einem Verschluss auf. Hier ist ein Artikel über Schließungen und wie mit ihnen zu arbeiten. Schauen Sie sich Beispiel 5 auf der Seite; Das ist das Szenario, das Sie es zu tun hat.

EDIT: Vier Jahre später, ist diese Verbindung tot. Die Wurzel des Problems ist, dass die oben for Schleife bildet Verschlüsse (insbesondere auf marker = results[i]). Als marker in addEventListener geführt wird, sehen Sie die Nebenwirkung des Verschlusses: die gemeinsame „Umwelt“ wird mit jeder Iteration der Schleife aktualisiert, bevor es schließlich ist über die Schließung nach der letzten Iteration „gerettet“. MDN dies sehr gut erklärt.

for (var i = 0; i < results.length; i++) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', (function(i) {
        return function(){
            change_selection(i);
        }
    })(i)); 
}

ich denke, wir eine temporäre Variable definieren den Wert von i zu speichern.

for (var i = 0; i < results.length; i++) {
 var marker = results[i];
 var j = i;
 google.maps.event.addListener(marker, 'click', function() { 
   change_selection(j);
 }); 
}

Ich habe nicht getestet es aber.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top