2016-01-10 13 views
11

Rozważmy następujący kod urywkiDlaczego "for (a)" poprawnie iteruje tablicę?

var a = [1, 2, 3, 4]; 
for (a of a) { // The first 'a' is made by mistake 
    console.log(a); 
} 

Pierwszy a w pętli for został napisany przez pomyłkę. Myślę, że powyższy kod powinien uruchomić błąd, ponieważ kiedy a jest przypisany do 1 w pierwszej iteracji, to a nie jest obiektem o numerze iterowalnym. Tak więc błąd powinien zostać odrzucony w następnej iteracji.

Faktycznie, wyniki są następujące:

1 
2 
3 
4 

Wydaje się, że powyższy kod może prawidłowo iterację tablicę. Po pętli for wynikiem a jest 4. Dlaczego?

> a 
4 

do dalszych badań, próbowałem znaleźć jakieś informacje od ECMA-6 doc, ale jestem zdezorientowany poniższej instrukcji.

dla (var ForBinding z AssignmentExpression) Rachunek

do (ForDeclaration z AssignmentExpression) Rachunek

do zrozumienia ForBinding i ForDeclaration przetestować następujące kodu.

var a = [1, 2, 3, 4]; 
for (var a of a) { 
    console.log(a); 
} 
console.log(a); 

Niestety, wynik jest taki sam jak poprzednie kody. Jaka jest różnica między for (var a in a) i for (a in a)?

Odpowiedz

9

for ocenia wartość "AssignmentExpression" i iteruje nad nim. Wartość jest uzyskiwana tylko raz na początku iteracji, więc ponowne użycie tej samej zmiennej jest całkowicie poprawne (również dość mylące).

Obecność var: for (a of ...) i for (var a of ...) nie ma żadnego różnicę w kodzie jak masz już a zdefiniowane - tak to będzie po prostu ponownie zadeklarować taką samą zmienną.


Aby być całkowicie precyzyjny istnieją przypadki, w których zachowanie jest inaczej - gdy a jest zadeklarowana w zakresie zewnętrznej dla bieżącej funkcji var wersji będzie cień, który wartości (jak w JavaScript wszystkie var oświadczenia są podciągnięta do góry zakresu funkcji):

var a = [1,2,3]; 
function tryForVar() { 
    // Note that declaration of `a` is hoisted here as var a = undefined; 
    // for (var a ... does not work as expected as local 'a' is undefined 
    for (var a of a) { 
    console.log(a); // log 'undefined' once 
    } 
    console.log(a); // undefined 
} 
tryForVar(); 
console.log(a); // [1,2,3] 

function tryFor() { 
    // Note that declaration of `a` from outer scope 
    // for (a ... works fine as it uses outer 'a' 
    for (a of a) { 
    console.log(a); // logs all 1,2,3 in sequence 
    } 
    console.log(a); // 3 
} 
tryFor(); 
console.log(a); // 3 
+0

Wydaje się, że jest to jedyna odpowiedź, która w rzeczywistości odnosi się do pytania i wydaje się być jedyną poprawną odpowiedzią. Nie wiem, dlaczego ktoś inny dał mu głos. +1 ode mnie. – jfriend00

+6

Nie głosowałem, ale zmienne zadeklarowane z 'var' nie są ponownie zadeklarowane. Deklaracje są wyciągane w swoim zasięgu, a 'var's spełniony później w kodzie są _ignored_. – Teemu

+1

@Teemu tak, moje stwierdzenie jest w istocie uproszczeniem i zamiast tego powinno brzmieć "jeśli użyjesz wersji' var a', znaczenie 'a' przed i po pętli będzie nadal takie samo, ale może śledzić zmienne z zewnętrznego zakresu dzięki podnoszeniu (a więc całkowicie zmienia to, co powtarzacie) ". –

Powiązane problemy