为什么在控制台的JavaScriptvariables声明导致“undefined”被打印?
我已经阅读了以下SOpost:
为什么这个JavaScript代码在控制台上显示“undefined”?
为什么Chrome和FireFox控制台不能打印?
为什么JS控制台返回一个额外的未定义?
但是没有一个解释了为什么当我声明一个variables的时候,JavaScript控制台打印的时候没有定义如下:
var a;
它打印这个expression式的结果 – 这是undefined
。 是的, var a
是一个有效的expression式。
实际上,当你写var a = 3
东西的时候,你应该为什么console
打印undefined
而感到好笑。 如果function anyFunctionName() {}
语句被处理,它也打印undefined
。 实际上,如果有另外一个带有“真实”结果的语句,那么所有的var
和function
声明(!)语句都会被忽略:
>>> var a = 3; undefined >>> var a = 3; a = 4; 4 >>> var a = 3; a = 4; var a = 5; function f() {}; 4 // !!!
现在,我想背后的真正原因是eval
语句的行为,如下所述:
- 让
result
成为评估程序的结果。- 如果
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)
。 所以脚本结束了第一个语句的结果(从脚本的结尾开始,所以在技术上它是最后一个),不是(normal, empty, empty)
。 这是a = 4
赋值语句的结果 – 这是4
。
PS现在为了一些锦上添花:考虑以下几点:
>>> function f() {} undefined >>> (function f() {}) function f() {}
区别是相当微妙的:第一个input被视为一个Function Declaration
语句,根据这个规则…
生产SourceElement : FunctionDeclaration的计算方法如下:
- 返回(正常,空,空)。
正如我们已经知道的那样,最终会产生undefined
eval
。
然而,第二个input被视为一个Function Expression
,该Function Expression
对函数本身进行求值。 这意味着它将通过eval
传递并最终返回到控制台(以其格式)。
因为你所做的只是声明有一个variables – 这是什么? 一个string,一个整数,一个布尔值 – 我们还不知道 – 因此undefined
var a=1; a
得到:
1
而
var a=1;
得到:
undefined
在第一种情况下控制台评估一个,所以它打印一个值
在第二种情况下,控制台不会评估a的值,但会评估expression式本身。