我已阅读以下SO帖子:
Why does this JavaScript code print “undefined” on the console?
Why does Chrome & FireFox console print undefined?
Why does the JS console return an extra undefined?
但是,当我按如下方式声明变量时,没有一个能解释为什么JavaScript控制台会打印 undefined :
var a;
答案 0 :(得分:32)
它打印此表达式的结果 - 即 undefined
。是的,var a
本身就是一个有效的表达式。
实际上,当您编写console
或类似内容时,您应该对undefined
打印var a = 3
的原因感到好笑。如果处理undefined
语句,它还会打印function anyFunctionName() {}
。实际上,如果有另一个带有“真实”结果的语句,那么所有var
和function
声明(!)语句似乎都会被忽略:
>>> var a = 3;
undefined
>>> var a = 3; a = 4;
4
>>> var a = 3; a = 4; var a = 5; function f() {};
4 // !!!
现在,我认为背后的真正原因是eval
语句的行为,如here所述:
- 让
result
成为评估计划prog
的结果。- 如果
result.type
为normal
且其完成值为value V
,则返回value V
。- 如果
result.type
为normal
且其完成值为empty
,则返回值undefined
。
现在的问题是,var a = 4
语句返回是什么?猜猜看:它不是4。
生产 VariableStatement : var VariableDeclarationList; 是 评估如下:
- 评估VariableDeclarationList。
- 返回(正常,空,空)。
现在最有趣的部分:在最后一个例子中发生了什么,为什么4是结果?这在this section中解释:
制作计划: 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
。
P.S。现在,为了一些锦上添花:考虑以下几点:
>>> function f() {}
undefined
>>> (function f() {})
function f() {}
区别非常微妙:第一个输入被视为Function Declaration
语句,根据此规则......
正如我们已经知道的那样,生产 SourceElement : FunctionDeclaration 评估为 如下:
- 返回(正常,空,空)。
...最终会产生undefined
eval
。
然而,第二个输入被视为Function Expression
,其被评估为to the function itself。这意味着它将通过eval
传递并最终返回到控制台(格式)。
答案 1 :(得分:3)
因为你所做的只是声明有一个变量 - 它是什么?字符串,整数,布尔值 - 我们还不知道 - 因此undefined
答案 2 :(得分:3)
var a=1;
a
给出:
1
,而
var a=1;
给出:
undefined
在第一种情况下,控制台评估a,因此它打印了
的值在第二种情况下,控制台不评估a的值,但它会评估表达式本身。
答案 3 :(得分:0)
每次评估一行代码时,您都会得到一个完成类型/记录 dumps
,它具有 3 个属性:import requests
import json
with open("myfile.txt", "w") as output:
resp = requests.get("https://jsonplaceholder.typicode.com/todos/1")
output.write(json.dumps(resp.json()))
、result
和 type
。根据{{3}}:
如果 value
是正常的并且它的完成值为值 target
,则返回值 result.type
。
如果 V
是正常的并且其完成值为 V
,则返回值 result.type
。
事实证明,当您声明变量或函数时,empty
是 undefined
。由于 completion type
为 (normal,empty,empty)
且值为 result.type
,因此它返回值 normal
。
但是,当您键入 empty
时,它是一个赋值表达式,其完成类型为 undefined
。因此,您只会在控制台中看到 a = 3
。
有关 (normal, GetValue(), empty)
和 3
的术语,请参阅 Ecma specification。
对于不同的完成类型值,请参见difference statement/expression。
如果您查看完成类型文档,您可以看到空语句 statement
也有一个完成类型 expression
(因此它应该返回 ;
),确实如此。出于同样的原因,(normal, empty, empty)
也返回 undefined
和 if (x>3) {console.log(x)}
。
但是,undefined
不返回 do {console.log(3);} while (false)
,因为它是一个表达式语句。
自行测试。以下是更多示例:
(function f(){})