#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. Я не голосовал против. Мой вопрос был о том, как получить результат оценки блока , который также представлен фигурными скобками. Я не спрашиваю об объектных литералах.