2011-11-10 5 views
9

Zauważyłem interesujący wynik z JSLint podczas badania pytania codereview. JSLint narzekał, że zmienna była używana przed jej zdefiniowaniem. Oto skrócona wersja kodu, który daje ten sam wynik:Zmienna słowa kluczowego w wyrażeniach try/catch: błąd JSLint lub zadanie globalne?

(function() { 
    try { 
     var a = 0; 
     throw { name: "fakeError" }; 
    } catch (e) { 
     a = 1; 
    } 
}()); 

Moje rozumienie JavaScript mówi, że powyższy kod powinien być równoważny:

(function() { 
    var a; 
    try { 
     a = 0; 
     throw { name: "fakeError" }; 
    } catch (e) { 
     a = 1; 
    } 
}()); 

i rzeczywiście, ani przykład powoduje a istnieć w zasięgu globalnym po uruchomieniu przez Firebug. Spojrzałem na sekcję 12.14 z ECMA-262 spec, ale nie widzę niczego, co mogłoby doprowadzić mnie do myślenia, że ​​funkcje powinny być traktowane inaczej. Czy jest to tylko błąd w JSLint, czy te dwa wyrażenia różnią się w pewien funkcjonalny sposób?

Odpowiedz

5

To tylko błąd, ale domyślne opcje JSLint wolałyby, gdyby mimo wszystko przenieść wszystkie instrukcje var na górę.

1

Podczas zamykania jakiś blok kodu z klamrami {...} tylko nie stwarza nowe możliwości w Javascript catch wyjątkiem jest, jak wspomniano w ECMAScript 5 spec. Kod wewnątrz bloku catch ma inny zakres w porównaniu do kodu zewnętrznego. traktowane jak funkcje wewnętrzne.

Innymi słowy, jak zauważono here:

Blok catch jest wyjątkowy w tej JavaScript tworzy ten identyfikator, gdy blok catch jest wprowadzony i dodaje go do bieżącego zakresu; identyfikator trwa tylko przez czas trwania bloku catch; po wykonaniu bloku catch, identyfikator nie jest już dostępny.

function f() { 
    try { 
    throw "foo"; 
    } catch (e) { 
    } 
    // e undefined here 
} 

A jak wiadomo, nie można oczekiwać zmiennej podnośnika od 2 różnych zakresów kodu w JavaScript. Tak więc JSLint narzeka, ponieważ on/ona ;-) wie o tym.

Powiązane problemy