2009-10-02 5 views
15

In Firefox 3.5, ich schreibe dies in der Konsole Firebug:JavaScript: {} == false ist ein SyntaxError?

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

Was hierfür ist die Erklärung?

+19

Sein JavaScript ... damit umgehen. –

+1

Interessant, aber was genau ist der Zweck davon? –

+2

hm, 'false == {}' evals zu 'false' in meinem Firefox 3.5.3 – SilentGhost

Antwort

41
{ 

zu Beginn einer Anweisung Signale ein 'Anweisungsblock' (siehe ECMA-262-3 Abschnitt 12.1), enthält eine Liste von Anweisungen.

} 

beendet sofort den Anweisungsblock mit keinen Anweisungen darin. Das ist gut. Aber jetzt sucht der Parser nach der nächsten Anweisung:

==false 

Huh? Das ist keine Aussage; Syntax-Fehler.

Was sind Anweisungsblöcke für?Nun, Sie werden jedes Mal ein Anweisungsblock Schreiben Sie sagen:

if (something) { 
    ... 
} 

JavaScript definiert diese Flow-Control-Anweisungen wie:

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

dh. in der einzigen Aussageform ohne Klammern. Es ermöglicht Ihnen dann, einen Anweisungsblock überall dort zu verwenden, wo Sie eine einzelne Anweisung verwenden können, was bedeutet, dass Sie if-braces-many-statements haben können. Es bedeutet aber auch, dass Sie selbst einen Anweisungsblock ohne zugehörige Flow-Control-Anweisung haben können.

Dies dient absolut keinem praktischen Zweck! Man könnte versucht zu denken, es gibt Ihnen Informationen deckenden, aber nicht:

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

... Ergebnisse in 2, weil Anweisungsblocks für sich allein nicht einen neuen Bereich erstellen.

JavaScript definiert Ablaufsteuerungs- und Anweisungsblöcke auf diese Weise, weil C (und andere davon abgeleitete Sprachen) dies getan haben. Diese Sprachen haben {} nicht als Objekt-Literalausdruck dienen, so dass sie nicht die Mehrdeutigkeit hatten, die dies zu einem anderen JS-Fehlverhalten macht.

Auch dieses wannabe-wörtliche:

{ 
    a: 1 
} 

ist ein gültiger Anweisungsblock, weil ‚:‘ verwendet wird, ein Etikett in einer Erklärung zu bezeichnen. (und 1 ist eine nutzlose Ausdruckanweisung, wobei das Semikolon weggelassen wird.) Beschriftungen sind ein weiteres von C geerbtes Feature, das in JavaScript nur selten verwendet wird. Sie sind nicht völlig sinnlos wie die Blöcke, aber sie werden selten gebraucht und oft als geschmacklos betrachtet.

(Eine wörtliche mit zwei Eigenschaften wird einen Syntaxfehler verursachen, als Objektliterale Komma Separatoren verwenden, aber etikettierten Anweisungen durch ein Semikolon getrennt werden müssen.)

Dies ist not the only place wo JavaScript lösen Syntax Sie up, indem sie stolpern kann eine andere Aussage von etwas, von dem Sie denken, dass es ein Ausdruck ist.

+0

And ({}) == false funktioniert. –

+0

Ja, und! {} == true funktioniert auch! – glmxndr

+4

Ja und Ei!== Rote Beete ist auch falsch, weil Sie schlagen und Ei können, aber Sie können eine Wurzel nicht schlagen. – Evernoob

11

OK, ich habe die studiert und ich habe eine Erklärung, die die BNF grammar diskussiert.

ECMAScript Quellen sind mit dem Hauptsymbol geparst beginnend genannt Program:

Program: 
    SourceElements 

SourceElements' (rekursiv) Definition ist folgende:

SourceElements : 
    SourceElement 
    SourceElements SourceElement 

Das wird SourceElement definiert als:

SourceElement : 
    Statement 
    FunctionDeclaration 

Was uns interessiert, ist die Objekt-Literal-Syntax, so dass wir ignorieren FunctionDeclaration und Blick auf die Erklärung Symbol:

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

Ich bin nicht sicher, ob die Auflistung um Angelegenheiten (dies ist, wie sie in der Spezifikation sind), aber ... ein Objektliteral ist ein ExpressionStatement, über die sagen, dass die Normen der folgenden (Abschnitt 12.4):

Beachten sie, dass ein ExpressionStatement nicht mit einer Öffnung geschweiften Klammer beginnen kann, weil dass es zweideutig mit einem Block machen könnte. Außerdem kann ein ExpressionStatement nicht mit dem Funktionsschlüsselwort beginnen, da es es mit einer FunctionDeclaration möglicherweise mehrdeutig machen kann.

So können wir einen Ausdruck zu Beginn des Programms haben, aber es muss nicht mit einer Öffnung geschweifte Klammer ({) beginnen. Deshalb ist die folgende Arbeit OK:

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

-1 Ist keine echte Antwort (.. oder vielleicht bekomme ich nur Ihren Standpunkt nicht). Fühlen Sie sich frei, mich aufzuklären :) – roosteronacid

+0

Sie sind völlig richtig. Ist eher ein Workaround. Ich durchsuche die ECMAScript 3-Spezifikation, um die richtige Antwort zu finden. Ich bin auch neugierig. –

+0

Aye. Ich habe meine Down-Abstimmung aufgehoben. – roosteronacid

0

Einfach zu sagen, {}==false werden von Js Compiler zu {};==false kompiliert, so ist es Syntaxfehler. Sie sollten ({})==false schreiben und es wird false zurückgeben.