2009-10-02 12 views
15

In Firefox 3.5, sto scrivendo questo nella console Firebug:JavaScript: {} == false è un SyntaxError?

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

Qual è la spiegazione per questo?

+19

Il suo JavaScript ... ha a che fare con esso. –

+1

Interessante, ma qual è esattamente lo scopo? –

+2

hm, 'false == {}' evalsa a 'false' nel mio Firefox 3.5.3 – SilentGhost

risposta

41
{ 

all'inizio di una dichiarazione segnala un 'blocco di istruzioni' (vedi ECMA-262-3 sezione 12.1), che contiene un elenco di dichiarazioni.

} 

termina immediatamente il blocco di istruzioni senza istruzioni in esso. Va bene. Ma ora il parser sta cercando la prossima affermazione:

==false 

Huh? Questa non è una dichiarazione; Errore di sintassi.

A cosa servono i blocchi di istruzioni?Bene, si sta scrivendo un blocco di istruzioni ogni volta che si dice:

if (something) { 
    ... 
} 

JavaScript definisce queste affermazioni flusso di controllo come:

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

es. nella singola forma di istruzione senza parentesi. Quindi consente di utilizzare un blocco di istruzioni ovunque sia possibile utilizzare una singola istruzione, il che significa che è possibile avere if-braces-many-statements. Ma significa anche che puoi avere un blocco di istruzioni da solo senza alcuna dichiarazione di controllo del flusso associata.

Questo non serve assolutamente a scopo pratico! Si potrebbe essere tentati di pensare che ti ha dato informazioni-nascondiglio, ma no:

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

... risultati in 2, perché blocchi di istruzioni per sé non creare un nuovo ambito.

JavaScript definisce il controllo di flusso ei blocchi di istruzioni in questo modo perché C (e altri linguaggi derivati ​​da esso) lo hanno fatto. Quelle lingue non hanno reso {} il servizio double-duty come un'espressione letterale Object, quindi non avevano l'ambiguità che rende questo un altro JS misfeature.

Anche questo wannabe-letterale:

{ 
    a: 1 
} 

è un blocco di istruzioni valida, perché ‘:’ è usato per indicare un'etichetta in un comunicato. (e 1 è un'istruzione espressione inutile, con il punto e virgola omesso.) Le etichette sono un'altra caratteristica ereditata da C che vengono raramente utilizzate in JavaScript. Non sono del tutto inutili come i blocchi, ma sono raramente necessari e spesso considerati di cattivo gusto.

(Un letterale con due proprietà causerà un errore di sintassi, come letterali oggetto usano separatori virgola, ma etichettati dichiarazioni devono essere separati da un punto e virgola.)

Questo è not the only place in cui la sintassi allentata di JavaScript può viaggio fino facendo qualche altra affermazione di qualcosa che pensi sia un'espressione.

+0

E ({}) == false opere. –

+0

Sì, e! {} == true funziona anche! – glmxndr

+4

sì e uovo!== anche la barbabietola rossa è falsa, perché puoi battere e sbattere ma non puoi battere una radice. – Evernoob

11

OK, ho studiato il ECMAScript specification (PDF) e ho una spiegazione che discute il BNF grammar.

fonti ECMAScript vengono analizzati iniziando con il simbolo principale, chiamata Program:

Program: 
    SourceElements 

SourceElements' (ricorsiva) definizione è questa:

SourceElements : 
    SourceElement 
    SourceElements SourceElement 

Il, SourceElement è definito come:

SourceElement : 
    Statement 
    FunctionDeclaration 

Ciò che ci interessa è la sintassi letterale dell'oggetto, così ignoriamo FunctionDeclaration e guardiamo il simbolo Dichiarazione:

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

Non sono sicuro se le questioni di ordine parola (è il modo in cui sono nelle specifiche), ma ... un oggetto letterale è un ExpressionStatement, sul quale le norme dicono seguente (sezione 12.4):

noti che un ExpressionStatement non può iniziare con un'apertura ricci tutore perché potrebbe rendere ambiguo con un blocco. Inoltre, un ExpressionStatement non può iniziare con la parola chiave della funzione poiché tale potrebbe renderlo ambiguo con una FunctionDeclaration .

Così possiamo avere un'espressione all'inizio del programma, ma non deve iniziare con una parentesi graffa di apertura ({). Ecco perché i seguenti lavori OK:

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

-1 Non è una risposta reale (.. o forse non sto ottenendo il tuo punto). Sentiti libero di illuminarmi :) – roosteronacid

+0

Hai perfettamente ragione. È piuttosto una soluzione. Sto cercando attraverso le specifiche ECMAScript 3 per trovare la vera risposta. Anch'io sono curioso anch'io. –

+0

Sì. Ho annullato il mio voto negativo. – roosteronacid

0

Semplicemente per dire, {}==false sono compilati dal compilatore Js a {};==false, quindi è un errore di sintassi. dovresti scrivere ({})==false e restituirà false.

Problemi correlati