2016-06-30 13 views
5

Im documentation for the let statement in MDN, gibt es in diesem Beispiel Code:Wie Variablen tut definiert mit `let` Akt in einer` for` Schleife

var list = document.getElementById("list"); 

for (let i = 1; i <= 5; i++) { 
    let item = document.createElement("li"); 
    item.appendChild(document.createTextNode("Item " + i)); 

    item.onclick = function (ev) { 
    console.log("Item " + i + " is clicked."); 
    }; 
    list.appendChild(item); 
} 

Dann geben sie an:

Das obige Beispiel funktioniert wie beabsichtigt weil die fünf Instanzen der (anonyme) innere Funktion auf fünf verschiedene Instanzen der Variable i beziehen.

Ich verstehe nicht, warum es „fünf verschiedene Instanzen der Variablen i.

Die erste Anweisung in einer for Schleife immer einmal ausgeführt wird, nicht wahr? Also die let Anweisung soll nur ausführen einmal ...
Sobald der Code erreicht das Ende der Iteration es um den Zustand in der zweiten Anweisung überprüft.

Wie kommt es, je nachdem, was sie schreiben, gibt es eine neue Instanz von i bei jeder Iteration?

+0

Nicht das, was Sie fragen, aber ich habe dieses Verhalten letzte Woche getestet und festgestellt, dass IE es nicht richtig implementiert. (Chrome tat.) – nnnnnn

+1

In ECMA 6-Spezifikation, wenn der Ausdruck ist Jede Iteration erstellt einen neuen lexikalischen Bereich, der an den vorherigen Bereich angekettet ist. http://www.ecma-international.org/ecma-262/6.0/#sec-for-statement-runtime-semantics-labelledevaluation –

+0

Um das zu verstehen ändere das 'let' in eine' var' und schau was passiert, wenn du auf die von der Schleife erzeugten Elemente klickst – Jamiec

Antwort

3

Wenn der Ausdruck let verwendet wird, erstellt jede Iteration einen neuen lexikalischen Bereich, der an den vorherigen Bereich angekettet ist.

Dies bedeutet, dass jede Schließung eine andere Instanz erfasst.

Das ist nach ECMA 6 specification aber nicht sicher, dass es in allen Browsern gleich funktioniert.

Auch nicht sicher über die Auswirkungen auf die Leistung. Ich würde diese Funktion lieber verwenden.

+0

Bevor 'let' IIFEs verwendet wurden um den gleichen Effekt zu erzielen - mit wahrscheinlich noch schlechterer Leistung. Was ist deine Empfehlung? – ftor

+0

@ LUH3417 Ich sage nur, ich bin nicht sicher über die Leistung eines solchen Konstrukts in verschiedenen Browsern. Zum Beispiel, werfen Sie einen Blick auf dieses Problem berichtet für Chrom https://bugs.chromium.org/p/v8/issues/detail?id=4762 –

+0

@ LUH3417 und ja, wahrscheinlich sind ify-s noch schlechter in Bezug auf die Leistung . Also würde ich an dieser Stelle lieber gar nichts empfehlen –

0

In JavaScript sind Variablen traditionell Funktionsbereich. Blöcke wie Schleifenanweisungen erstellen keinen neuen Bereich.

Wenn Sie eine Variable mit var überall in Ihrer Funktion deklarieren (zum Beispiel in einem for-Schleife), wird es nur einmal an der Spitze des Bereichs erklärt seine dank hoisting, und es wird nur eine Instanz davon im gesamten Funktionsumfang.

Es kann zu Problemen kommen, wenn Sie Callbacks innerhalb einer for ... -Schleife aufrufen.

// with hoisting, i is only declared once 
for (var i in items) { 
    // the fn is called items.length times, before any callback is invoked 
    _fetchItems(items[i], function() { 
     console.log("fetched for ", items{i]); 
     // for all callbacks, i is the same value items.length-1 
     // because they are called after the loop is complete 
    }); 
} 

Oder in Ihrem Beispiel:

// with hoisting, i is only declared once 
for (var i = 1; i <= 5; i++) { 

    // with hoisting, item is only declared once 
    var item = document.createElement("li"); 
    item.appendChild(document.createTextNode("Item " + i)); 

    // this function will be called after the for...loop is complete 
    // so i value is unique: 5 + 1 = 6 
    item.onclick = function (ev) { 
     // => always return "Item 6 is clicked" 
     console.log("Item " + i + " is clicked."); 
    }; 
    list.appendChild(item); 
} 

Auf der gegenüberliegenden, let Variablen sind nur auf den nächsten Block scoped (dh jeder Codeabschnitt zwischen geschweiften Klammern.).

In Ihrem Beispiel wird eine neue Instanz der Variablen i für jede Ausführung des Blocks innerhalb der for ... -Schleife deklariert. i geht von 1 bis 5, also gibt es 5 Ausführungen des Blocks, also 5 Instanzen der Variablen.

Sie werden jeweils den erwarteten Wert "Punkt 1 ist geklickt.", "Punkt 2 wird geklickt.", etc.

+0

Der Punkt ist, dass die erste Anweisung in einer For-Schleife immer einmal ausgeführt wird. wie folgt ausgeführt werden: für (var i = 1; i ++; i <5) {lege t = i; ...} würde keine Fragen verursachen. –