var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
Sie gibt dies aus:
Mein Wert: 3
Mein Wert: 3
Mein Wert: 3
Ich hingegen möchte, dass es ausgegeben wird:
Mein Wert: 0
Mein Wert: 1
Mein Wert: 2
Das gleiche Problem tritt auf, wenn die Verzögerung bei der Ausführung der Funktion durch die Verwendung von Ereignis-Listenern verursacht wird:
var buttons = document.getElementsByTagName("button");
// let's create 3 functions
for (var i = 0; i < buttons.length; i++) {
// as event listeners
buttons[i].addEventListener("click", function() {
// each should log its value.
console.log("My value: " + i);
});
}
<button>0</button>
<br />
<button>1</button>
<br />
<button>2</button>
oder asynchroner Code, z.B. mit Promises:
// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));
for (var i = 0; i < 3; i++) {
// Log `i` as soon as each promise resolves.
wait(i * 100).then(() => console.log(i));
}
Das zeigt sich auch in for in
y for of
Schleifen:
const arr = [1,2,3];
const fns = [];
for(var i in arr){
fns.push(() => console.log(`index: ${i}`));
}
for(var v of arr){
fns.push(() => console.log(`value: ${v}`));
}
for(var f of fns){
f();
}
Was ist die Lösung für dieses grundlegende Problem?
62 Stimmen
Sind Sie sicher, dass Sie nicht wollen, dass
funcs
ein Array zu sein, wenn Sie numerische Indizes verwenden? Nur eine Vorwarnung.33 Stimmen
Das ist ein wirklich verwirrendes Problem. Diese Artikel hilft mir, ihn zu verstehen . Vielleicht hilft es ja auch anderen.
4 Stimmen
Eine weitere einfache und gut erklärte Lösung: 1) Verschachtelte Funktionen Zugriff auf den Bereich "über" ihnen haben ; 2) a Verschluss Lösung ... "Eine Schließung ist eine Funktion, die Zugriff auf den übergeordneten Bereich hat, auch nachdem die übergeordnete Funktion geschlossen wurde".
2 Stimmen
Siehe diesen Link zum besseren Verständnis javascript.info/tutorial/advanced-functions
61 Stimmen
Unter ES6 ist eine triviale Lösung die Deklaration der Variablen i mit lassen Sie die auf den Körper der Schleife beschränkt ist.
4 Stimmen
JS-Funktionen "verschließen" den Bereich, auf den sie bei der Deklaration Zugriff haben, und behalten den Zugriff auf diesen Bereich, auch wenn sich die Variablen in diesem Bereich ändern. Jede Funktion im obigen Array schließt sich über den globalen Bereich (global, einfach weil sie in diesem Bereich deklariert sind). Später werden diese Funktionen aufgerufen und protokollieren den aktuellsten Wert von
i
im globalen Bereich. Das ist JS : )let
anstelle vonvar
löst dieses Problem, indem es jedes Mal, wenn die Schleife ausgeführt wird, einen neuen Bereich erstellt, der für jede Funktion, die geschlossen werden soll, einen separaten Bereich erzeugt. Verschiedene andere Techniken tun das Gleiche mit zusätzlichen Funktionen.1 Stimmen
Eine ausführlichere Antwort finden Sie weiter unten: stackoverflow.com/a/41023816/1027004
0 Stimmen
Das Entwurfsmuster passt perfekt zu diesem Szenario stackoverflow.com/a/42512295/696535
0 Stimmen
Warum das nicht funktioniert - funcs[i] = function abc () { return function() { console.log("Mein Wert: " + i); };
0 Stimmen
Ein Beispiel für dieses Problem wurde hinzugefügt in
for in
yfor of
Schleifen.0 Stimmen
@S.D. Ich würde vorschlagen, zumindest die
var
Schlüsselwort für das hinzugefügte Beispiel. Die Verwendung globaler Variablen gilt als schlechte Praxis.for (var v of arr)
(Um das Problem zu lösen, verwenden Sielet
oconst
anstelle vonvar
.)0 Stimmen
@3limin4t0r Korrigiert.
3 Stimmen
Aus diesem Grund hasse ich Javascript.