Ответ 1
Он печатает результат этого выражения - undefined
. И да, var a
является правильным выражением.
На самом деле вам следует позабавиться, почему console
печатает undefined
при написании var a = 3
или что-то вроде этого. Он также печатает undefined
, если выполняется инструкция function anyFunctionName() {}
. На самом деле все инструкции var
и function
declare (!) Кажутся проигнорированными, если есть другой оператор с некоторым "реальным" результатом:
>>> var a = 3;
undefined
>>> var a = 3; a = 4;
4
>>> var a = 3; a = 4; var a = 5; function f() {};
4 // !!!
Теперь я полагаю, что реальной причиной является поведение оператора eval
, как описано здесь:
- Пусть
result
будет результатом оценки программыprog
.- Если
result.type
-normal
, а его значение завершения -value V
, вернитеvalue V
.- Если
result.type
-normal
, а его значение завершенияempty
, верните значениеundefined
.
Итак, теперь вопрос в том, что возвращает оператор var a = 4
? Угадайте, что: это не 4.
Производство VariableStatement: var VariableDeclarationList; является оценивается следующим образом:
- Оценить VariableDeclarationList.
- Возврат (обычный, пустой, пустой).
Теперь самая интересная часть: что произошло в последнем примере, почему 4 - результат? Это объясняется в этом разделе:
Производственная Программа: SourceElements оценивается следующим образом:
- Пусть результат будет результатом оценки SourceElements.
[...]
Источник SourceElements: SourceElements * SourceElement * оценивается следующим образом:
- Пусть headResult будет результатом оценки SourceElements.
- Если headResult является неожиданным завершением, верните headResult.
- Пусть tailResult является результатом оценки SourceElement.
- Если tailResult.value пуст, пусть V = headResult.value, в противном случае пусть V = > tailResult.value.
- Возврат (tailResult.type, V, tailResult.target)
Оба возвращаемых значения function f() {}
и var a = 5
были (normal, empty, empty)
. Таким образом, script закончил выдачу результата первого оператора (начиная с конца script, так что технически это последний), а не (normal, empty, empty)
. Это результат оператора присваивания a = 4
- 4
.
P.S. И теперь для некоторой глазури на торте: рассмотрите следующее:
>>> function f() {}
undefined
>>> (function f() {})
function f() {}
Разница довольно тонкая: первый вход рассматривается как оператор Function Declaration
, который, согласно этому правилу...
Производство SourceElement: FunctionDeclaration оценивается как следующим образом:
- Возврат (обычный, пустой, пустой).
... в конечном итоге произведет undefined
, когда eval
-ed, как мы уже знаем.
Второй вход, однако, рассматривается как Function Expression
, который оценивается самой функции. Это означает, что он будет передан через eval
и в конечном итоге вернется на консоль (в его формате).