2009-10-02 14 views
15

W Firefoksie 3.5, wpisuję to w konsoli Firebug:JavaScript: {} == false to błąd SyntaxError?

false=={} // => evals to false 
{}==false // syntax error 

Jakie jest wytłumaczenie tego?

+19

Jego JavaScript ... sobie z tym poradzić. –

+1

Interesujące, ale jaki jest dokładnie cel tego? –

+2

hm, 'false == {}' evals to 'false' w moim Firefox 3.5.3 – SilentGhost

Odpowiedz

41
{ 

na początku instrukcji sygnalizuje "blok oświadczenie (zob ECMA-262-3 rozdział 12.1), który zawiera listę wyciągów.

} 

natychmiast kończy blok instrukcji bez żadnych instrukcji. W porządku. Ale teraz parser szuka następnej instrukcji:

==false 

Huh? To nie jest oświadczenie; błąd składni.

Do czego służą bloki instrukcji?Cóż, piszesz bloku komunikat za każdym razem mówisz:

if (something) { 
    ... 
} 

JavaScript definiuje te oświadczenia kontroli przepływu jak:

if "(" <expression> ")" <statement> [else <statement>] 

tj. w pojedynczym formularzu oświadczenia bez żadnych nawiasów klamrowych. Następnie pozwala używać bloku instrukcji wszędzie, gdzie możesz użyć pojedynczej instrukcji, co oznacza, że ​​możesz mieć -sam-nawiasy-wiele-instrukcji. Ale oznacza to również, że możesz mieć własny blok instrukcji bez żadnego powiązanego oświadczenia kontroli przepływu.

To absolutnie nie ma praktycznego zastosowania! Można ulec pokusie, aby myśleć, że dał ci ukrywania informacji, ale nie:

var a= 1; 
{ 
    var a= 2; 
} 
alert(a); 

... Wyniki w 2, ponieważ oświadczenie nie blokuje w sobie utworzyć nowy zakres.

JavaScript definiuje sterowanie przepływem i bloki instrukcji w ten sposób, ponieważ zrobił to C (i inne języki z niego wyprowadzone). Języki te nie sprawiały jednak, że {} służyły jako podwójny obowiązek jako dosłowne wyrażenie w Object, więc nie miały one dwuznaczności, która sprawia, że ​​jest to kolejna nieprawidłowość JS.

Nawet to wannabe-dosłowny:

{ 
    a: 1 
} 

jest ważny blok stwierdzenie, ponieważ „:” jest używany do oznaczenia etykietą w oświadczeniu. (i 1 jest bezużytecznym wyrażeniem-wyrażeniem, z pominięciem średnika.) Etykiety są kolejną cechą odziedziczoną po C, rzadko używaną w JavaScript. Nie są zupełnie bezsensowne jak klocki, ale rzadko są potrzebne i często traktowane w złym guście.

(Dosłowne z dwóch właściwości spowoduje błąd składni, jako literały obiektowe użyciu separatorów przecinek, ale oznakowane oświadczenia muszą być oddzielone średnikiem.)

To not the only place gdzie luźne składnia JavaScript w przeglądarce, może zadziałać cię dokonując inne stwierdzenie czegoś, co uważasz za wyrażenie.

+0

I ({}) == false działa. –

+0

Tak, i! {} == true również działa! – glmxndr

+4

tak i jajko!== Burak ćwikłowy jest również fałszywy, ponieważ możesz pokonać i jajko, ale nie możesz pokonać korzenia. – Evernoob

11

OK, zapoznałem się z ECMAScript specification (PDF) i mam wyjaśnienie, które omawia BNF grammar.

źródła ECMAScript są przetwarzane począwszy od głównego symbolu, zwany Program:

Program: 
    SourceElements 

SourceElements' (rekurencyjny) określenie to:

SourceElements : 
    SourceElement 
    SourceElements SourceElement 

La, SourceElement jest zdefiniowany jako:

SourceElement : 
    Statement 
    FunctionDeclaration 

Co nas interesuje, to literalna składnia obiektu, więc ignorować FunctionDeclaration i spójrz na symbol oświadczenie:

Statement : 
    Block 
    VariableStatement 
    EmptyStatement 
    ExpressionStatement 
    IfStatement 
    IterationStatement 
    ContinueStatement 
    BreakStatement 
    ReturnStatement 
    WithStatement 
    LabelledStatement 
    SwitchStatement 
    ThrowStatement 
    TryStatement 

nie jestem pewien, czy w sprawach porządkowych aukcji (jest to w jaki sposób są one w ciemno), ale ... obiekt dosłowny jest ExpressionStatement, o których normy mówią następujące (rozdział 12.4):

pamiętać, że ExpressionStatement nie można uruchomić z otworem kręcone nawiasów, ponieważ mogłoby uczynić go niejednoznaczne z blokiem. Ponadto wyrażenie ExpressionStatement nie może rozpocząć się od słowa kluczowego funkcji, ponieważ ten może spowodować, że będzie on niejednoznaczny z funkcją FunctionDeclaration .

więc możemy mieć wyraz na początku programu, ale nie musi zaczynać się od otwarcia nawias klamrowy ({). Dlatego następujące prace OK:

  • ({} == false);
  • alert({} == false);
  • !{} == false;
+0

-1 Nie jest prawdziwą odpowiedzią (.. albo po prostu nie rozumiem). Zapraszam do oświecenia mnie :) – roosteronacid

+0

Masz całkowitą rację. To raczej obejście. Przeszukuję specyfikację ECMAScript 3, aby znaleźć prawdziwą odpowiedź. Ja też jestem ciekawy. –

+0

Aye. Usunąłem mój głos w dół. – roosteronacid

0

Po prostu powiedzieć, {}==false są kompilowane przez kompilator JS do {};==false, więc jest błąd składni. powinieneś napisać ({})==false, a to zwróci false.

Powiązane problemy