如果我打开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);