将block的结果赋值给一个变量(给出SyntaxError)



如果我打开Node REPL,并输入这段代码,我可以看到它的计算结果为3:

$ node
> { let a = 1 + 2; a }
3
> 

但是,这段代码不起作用:

const result = { let a = 1 + 2; a };

我得到这个错误:

const result = { let a = 1 + 2; a };
                     ^
SyntaxError: Unexpected identifier

我在这里错过了什么?假设块计算到其中的最后一个表达式是正确的,还是Node的REPL在这里误导了我?

正如您在Node REPL中看到的那样,一个块计算为一个值,该值通常是块中最后一条语句的值。

在ECMAScript 6.0中,BlockStatement的定义如下(为简单起见省略了下标):

BlockStatement:
    Block
Block:
    { StatementList }
StatementList:
    StatementListItem
    StatementList StatementListItem
StatementListItem:
    Statement
    Declaration

根据第13.2.13节,注2,"StatementList的值是StatementList中最后一个产生值的项的值"。Block被求值为StatementList的值,BlockStatement被求值为Block的值。

因此,Node正确地将BlockStatement计算为最后一个产生值的项目的值,即a。这不是一个bug,也不是Node特有的。

你得到一个错误的原因是因为你试图在一个不允许的上下文中使用BlockStatement

const result = { let a = 1 + 2; a };是一个LexicalDeclaration,其定义如下(同样省略下标):

LexicalDeclaration:
    LetOrConst BindingList ;
LetOrConst :
    let
    const
BindingList:
    LexicalBinding
    BindingList , LexicalBinding
LexicalBinding:
    BindingIdentifier Initializer
    BindingPattern Initializer
我们还需要Initializer的定义:
Initializer:
    = AssignmentExpression

可以看到,等号之后的词法声明部分需要一个AssignmentExpression。如果您查看表达式语法,您将看到BlockStatement不是AssignmentExpression

在ES6.0中,没有办法将BlockStatement直接用作AssignmentExpression。但是,如果您想将1求值为表达式,则可以使用eval:

> const result = eval("{ let a = 1 + 2; a }");
> result
3

我不建议在一般情况下这样做,但它有助于了解ES6.0如何将块计算为值。

在js中,花括号表示需要key: value对的对象。您可以得到这样的结果;

const result = {a: 1 + 2};
console.log(result.a);

最新更新