Когда JS интерпретирует {} как пустой блок вместо пустого объекта?
Я читал ответ на этот вопрос (о видео "Ват"), и он сказал:
{}+[]
Это интерпретируется как пустой блок кода, унарный плюс и пустой массив. Первая часть ничего не делает, массив преобразуется в разделенную запятыми строку его элементов (пустая строка для пустого массива), затем в число (пустая строка преобразуется в 0), следовательно, в 0.
В настоящее время я изучаю JS из "Полного руководства", поэтому я стараюсь по-настоящему понять такие вещи.
Мой вопрос, когда JS решает интерпретировать {}
как пустой блок кода, а не пустой объект?
Также есть некоторые несоответствия между Node.js и Firebug, которые я хотел бы понять.
Firebug:
{} [] code> и ({} []) code">
Node.js:
{} [] code> и ({} []) code">
2 ответа
Давайте посмотрим на грамматику языка, не так ли? Раздел 12, Заявления:
Statement :
Block
VariableStatement
EmptyStatement
ExpressionStatement
...lots of other stuff...
Это очень причудливый способ сказать, что оператор может быть блоком, оператором переменной, пустым оператором, оператором выражения или множеством других вещей. Обратите внимание, что первым вариантом является "Блок":
Block :
{ StatementList(opt) }
StatementList :
Statement
StatementList Statement
Что опять же, причудливый способ сказать, что блок является {
, за которым следует группа заявлений, а затем }
,
И это то, что вы видите в своем примере: прежде чем анализатор JavaScript подумает, что то, что у вас есть, может быть литералом объекта (который определен где-то в ExpressionStatement
, 4-ая вещь, которая может быть "Заявлением"), сначала она думает, что у вас есть "Блок".
Изменить: Если вы хотите, вы можете увидеть его вживую в исходном коде движка JavaScript:
- В V8, движке Chrome JavaScript, мы идем в
Parser::ParseStatement
, Первое, что он проверяет, находимся ли мы на{
и, если это так, анализируется как блок. - В SpiderMonkey, движке JavaScript Firefox, мы
Parser::statement
чтобы снова увидеть первую проверку против{
и разбор его как оператор блока.
Что касается вашего второго вопроса, он был подробно освещен по этому вопросу. Подводя итог предложению: Node.js обрабатывает ваш ввод, как если бы он был выражением (таким образом, он не может быть "блоком"), в то время как инструменты разработчика Firebug/Chrome воспринимают его как "выражение".
Когда первый токен в новом утверждении {
, затем {}
интерпретируется как пустой блок.
(Собственно конечно когда {
появляется после предложения заголовка чего-то вроде if
или же while
, затем {}
тоже пустой блок, но это не интересный случай.)
Таким образом, в любом другом контексте, например, в качестве аргумента функции:
foo({});
{}
интерпретируется как литерал пустого объекта.
Эта ситуация похожа на то, как function
Ключевое слово обрабатывается по-разному, когда это первое в утверждении. Синтаксис имеет неоднозначность, и синтаксический анализатор решает проблему с фиксированными правилами.