为什么控制台上的JavaScript变量声明会导致;“未定义”;正在印刷?
我已经阅读了以下SO帖子: 但这些都不能解释为什么当我声明一个变量时,JavaScript控制台会打印未定义的,如下所示:为什么控制台上的JavaScript变量声明会导致;“未定义”;正在印刷?,javascript,Javascript,我已经阅读了以下SO帖子: 但这些都不能解释为什么当我声明一个变量时,JavaScript控制台会打印未定义的,如下所示: var-a它打印此表达式的结果-它是未定义的。是的,var a本身就是一个有效的表达式 实际上,当您编写var a=3或诸如此类的内容时,为什么console会打印undefined。如果处理了function anyFunctionName(){}语句,它还会打印undefined。事实上,如果存在另一个具有某些“真实”结果的语句,则所有var和function声明
var-a代码>它打印此表达式的结果-它是未定义的
。是的,var a
本身就是一个有效的表达式
实际上,当您编写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
作为评估程序prog
的结果
- 如果
result.type
为normal
且其完成值为值V
,则返回值V
- 如果
result.type
为normal
且其完成值为空
,则返回值未定义
现在的问题是,var a=4
语句返回什么?猜猜怎么着:不是4
生产VariableStatement:var VariableDeclarationList;是
评价如下:
- 计算VariableDeclarationList
- 返回(正常、空、空)
现在最有趣的部分是:上一个例子中发生了什么,为什么结果是4?这在以下章节中进行了解释:
生产计划:SourceElements评估如下:
- 让result作为计算SourceElements的结果
[……]
生产SourceElements:SourceElements*SourceElement*的评估如下:
- 让headResult作为计算SourceElements的结果
- 如果headResult是突然完成,则返回headResult
- 让tailResult作为计算SourceElement的结果
- 如果tailResult.value为空,则让V=headResult.value,否则让V=>tailResult.value
- 返回(tailResult.type、V、tailResult.target)
函数f(){}
和var a=5
语句的返回值都是(正常、空、空)
。因此,脚本最后给出了第一条语句的结果(从脚本的结尾开始,所以从技术上讲,它是最后一条语句),这不是(正常、空、空)
。这是a=4
赋值语句的结果,即4
P.S.S.现在为蛋糕锦上添花:考虑以下内容:
>>> function f() {}
undefined
>>> (function f() {})
function f() {}
区别非常微妙:第一个输入被视为函数声明
语句,根据这条规则
productionSourceElement:FunctionDeclaration评估为
如下:
- 返回(正常、空、空)
。。。我们已经知道,当eval
-ed时,最终将产生undefined
但是,第二个输入被视为一个函数表达式
,并进行计算。这意味着它将通过eval
并最终返回控制台(以其格式)。因为您所做的只是声明存在一个变量-它是什么?一个字符串,一个整数,一个布尔值-我们还不知道-因此未定义
var a=1;
a
给出:
1
undefined
当
给出:
1
undefined
在第一种情况下,控制台计算a,以便打印a的值
在第二种情况下,控制台不计算a的值,但计算表达式本身。每次计算一行代码时,都会得到一个完成类型/记录结果
,它有3个属性:类型,值和目标。根据报告:
如果result.type
正常且其完成值为值V
,则返回值V
如果result.type
正常且其完成值为空
,则返回值未定义
事实证明,当您声明变量或函数时,完成类型是(正常、空、空)
。由于结果.type
为正常
且值为空
,因此它返回值未定义
但是,当您键入a=3
时,它是一个赋值表达式,其完成类型是(normal,GetValue(),empty)
。因此,您只需在控制台中看到3
有关语句
和表达式
的术语,请参阅
有关完成类型的不同值,请参见
如果查看完成类型文档,可以看到空语句
还有一个完成类型(normal,empty,empty)
(因此它应该返回undefined
),事实上就是这样。出于同样的原因,if(x>3){console.log(x)}
也返回undefined
和do{console.log(3);},而(false)
也返回
但是,(函数f(){})
不会返回未定义的
,因为它是一个表达式语句
自己测试。以下是更多的例子:
eval('function f(){}');//返回(正常、空、空)、未定义
求值(“;”);//返回(正常、空、空)、未定义
eval('(函数f(){});//(正常、GetValue(exprRef)、空)、ExpresionStatement
函数foo(){
返回4;
}//返回(norma