Присвоить результат блока переменной (дает синтаксическую ошибку)

#javascript

#javascript

Вопрос:

Если я открою 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
 

Что я здесь упускаю из виду? Правильно ли я предполагаю, что блок вычисляется до последнего выражения внутри него, или REPL узла вводит меня в заблуждение?

Комментарии:

1. Если вы начинаете с { того, что это блок, если у вас есть varName = { , это литерал объекта.

2. вы рассматриваете оператор блока как объект. это не работает.

3. Почему узел говорит, что блок оценивает что-то? Как я могу использовать то, что оценивает блок, если мне нужно его выбросить?

4. Блок не имеет значения. Вы никогда не сможете получить значение из самого блока — нет никакого способа иметь блок кода в контексте выражения. Что такое журналы REPL для удобства — кажется, он выбирает последнее утверждение. Это не отличается от объявлений переменных, которые также не дают никакого значения — это операторы , поэтому они также недопустимы в контекстах выражений. Тем не менее, консоль войдет undefined в систему, чтобы, по крайней мере, подтвердить, что код был обработан.

5. @Flimm можно использовать eval для получения последнего значения завершения блока (или любого другого оператора). Именно так это делает консоль. Однако вы никогда не должны использовать это.

Ответ №1:

Как вы видели в Node REPL, блок вычисляется до значения, и это значение обычно является значением последнего оператора в блоке.

В ECMAScript 6.0 a BlockStatement определяется следующим образом (для простоты индексы опущены):

 BlockStatement:
    Block

Block:
    { StatementList }

StatementList:
    StatementListItem
    StatementList StatementListItem

StatementListItem:
    Statement
    Declaration
 

Согласно разделу 13.2.13, примечание 2, «Значение a StatementList — это значение последнего элемента, производящего значение в StatementList .» A Block оценивается по значению its StatementList , а a BlockStatement оценивается по значению its Block .

Таким образом, узел правильно оценивает ваше BlockStatement значение по значению последнего элемента, производящего значение, которое есть a . Это не ошибка и не относится к узлу.

Причина, по которой вы получаете сообщение об ошибке, заключается в том, что вы пытаетесь использовать a BlockStatement в контексте, где это запрещено.

const result = { let a = 1 2; a }; является a LexicalDeclaration , который определяется следующим образом (опять же, с опущенными нижними индексами):

 LexicalDeclaration:
    LetOrConst BindingList ;

LetOrConst :
    let
    const

BindingList:
    LexicalBinding
    BindingList , LexicalBinding

LexicalBinding:
    BindingIdentifier Initializer
    BindingPattern Initializer
 

Нам также нужно определение Initializer :

 Initializer:
    = AssignmentExpression
 

Как вы можете видеть, часть вашего лексического объявления после знака равенства требует AssignmentExpression . Если вы просмотрите грамматику в поисках выражений, вы увидите, что BlockStatement это не an AssignmentExpression .

Начиная с ES6.0, нет способа использовать BlockStatement a напрямую как an AssignmentExpression . Однако, если вы хотите вычислить одно из выражений, вы можете использовать eval :

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

Я не рекомендую делать это при обычных обстоятельствах, но это полезно для того, чтобы увидеть, как ES6.0 действительно оценивает блоки по значениям.

Ответ №2:

В js фигурные скобки представляют объект, который ожидает key: value пары. Вы можете получить такой результат;

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

Комментарии:

1. Не могли бы вы, пожалуйста, объяснить, что не так в моем ответе. Спасибо!

2. Я не голосовал против. Мой вопрос был о том, как получить результат оценки блока , который также представлен фигурными скобками. Я не спрашиваю об объектных литералах.