何时(以及为什么)在JavaScript控制台中未定义?

JS_*_*ler 9 javascript console

在FF和Chrome的控制台中,{}在被明确评估之前被视为未定义:

{};     // undefined
({});   // ? Object
Run Code Online (Sandbox Code Playgroud)

实际上,它的定义不如未定义 - 它显然是错误的语法:

{} === undefined;  // SyntaxError: Unexpected token ===
{}.constructor;    // SyntaxError: Unexpected token .
Run Code Online (Sandbox Code Playgroud)

但不是如果它在另一边,在这种情况下它是好的:

"[object Object]" == {}.toString(); // true
Run Code Online (Sandbox Code Playgroud)

或者,如果它不是第一个表达式:

undefined + undefined; // NaN
{} + undefined;        // NaN
undefined + {};        // "undefined[object Object]"
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?

Guf*_*ffa 10

如果你自己使用大括号,它不是一个对象文字,它是一个代码块.由于代码块不包含任何代码,因此会对其进行评估undefined.


小智 6

好的,这是我的答案.这里没有什么新东西.我只是链接到语法的ECMAScript规范(的一个漂亮的副本),并显示一些产品,以显示它解析它的方式"为什么".在任何情况下,根据JavaScript/ECMAScript语法规则明确定义行为:{}根据它所处的"上下文"进行不同的解析.


JavaScript REPL("控制台")开始解析Statement语法生成或"语句上下文"中的代码.(这实际上是一个谎言,它始于ProgramSourceElements生产,但这增加了额外的结构来挖掘.)这是一个粗略的语法分解,简化和省略; 请参阅上面的链接了解更多:

Statement
    Block
    ...
    ExpressionStatement

Block
    # This is actually { StatementList[optional] }, but this is what
    # it amounts to: * means "0 or more".
    { Statement* }

ExpressionStatement
    # An ExpressionStatement can't start with "{" or "function" as
    # "{" starts a Block and "function" starts a FunctionStatement.
    [lookahead ? {{, function}]Expression ;

Expression
    # This is really PrimaryExpression; I skipped a few steps.
    ...
    ( Expression )
Run Code Online (Sandbox Code Playgroud)

因此(在"陈述语境中"):

   {}
-> Block  # with no StatementList (or "0 statements")
-> Statement
Run Code Online (Sandbox Code Playgroud)

和:

   ({})
-> (Expression)
-> Expression
-> ExpressionStatement  # omitted in productions below
-> Statement
Run Code Online (Sandbox Code Playgroud)

这也解释了为什么在评估时undefined === {}解析as EXPR === EXPR -> EXPR -> STMT并导致false.在{}这种情况下是"表达上下文".

如果{} === undefined它被解析为{}; === undefined,或者BLOCK; BOGUS -> STMT; BOGUS,它是一个语法错误.但是,通过添加括号,此更改:({} === undefined)被解析为(EXPR === EXPR) -> (EXPR) -> EXPR -> STMT.

{} + "hi"它的情况下被解析为{}; + "hi",或者BLOCK; + EXPR -> STMT; EXPR -> STMT; STMT,即使它是愚蠢的(+在这种情况下是一元的),这是有效的语法.同样,如上所述,"hi" + {}将其{}置于"表达式上下文"中并将其解析为EXPR + EXPR -> EXPR -> STMT.

JavaScript控制台只是显示最后一个Statement的结果,对于空{}块,它是"未定义的"(好吧,"没有"真的,但不存在).(在这种情况下,在浏览器/环境之间可能会有所不同,例如最后一个ExpressionStatement?)

快乐的编码.