JavaScript中的赋值和var关键字

6
我是一名有用的助手,可以为您翻译文本。
我正在阅读《学习Node》一书,并卡在一个非常简单的问题上,这是我没有太多考虑的问题:JavaScript中的赋值。
作者指出我们应该意识到,使用Node的REPL,以下内容将返回未定义:
var a = 2
(undefined)

在 REPL 中,下面的代码将返回 '2':

a = 2
2

为什么会这样?上面的代码不是赋值语句吗?为什么呢?如果直到那段代码之前变量'a'都不存在,它怎么可能不是一个赋值语句?

请查看https://dev59.com/aFjUa4cB1Zd3GeqPOBYg。 - moonwave99
1
为什么这个问题上有一个“浏览器”标签? - Lior
JS REPL在Firefox(Firebug)、Chrome和IE> 8中提供相同的结果。 - Draconar
4个回答

7
根据ECMA-262 § 12.2VariableStatement(即var identifier=value)明确地不返回任何内容。此外,VariableStatement是一个语句; 语句不返回值,并且在表达式所在的位置放置语句是无效的。
例如,以下所有内容都没有意义,因为它们在需要产生值的表达式位置上放置了语句:
var a = var b;
function fn() { return var x; }

根据§ 11.13.1,对一个变量(identifier=value)进行赋值会返回被赋的值。
当你写下var a = 1;时,它声明了a并将其值初始化为1。因为这是一个VariableStatement,它不返回任何内容,REPL打印undefineda=1是一个表达式,将1分配给a。由于没有a,JavaScript在普通代码中隐式创建一个全局a(但在严格模式下会抛出ReferenceError,因为不允许在严格模式下隐式创建新的全局变量)。
无论a之前是否存在,该表达式仍然返回分配的值1,因此REPL打印该值。

1
进一步阅读:您可能还对功能语句/声明和函数表达式之间的区别感兴趣(http://kangax.github.com/nfe/)。 - josh3736

1

这只是猜测 - 可以通过参考ECMAScript第5版规范来验证(但那玩意儿真的很麻烦) - 这可能与“var”语句的规范和将属性分配给“全局”对象有关。

当您声明一个变量并为其赋值(var a = 2)时,返回的值可能是“undefined”,因为规范规定“var”语句应返回该值。

当您将变量分配给符号而不使用“var”语句时,实际上是将该名称的全局对象的属性赋值给一个值。也就是说,a = 2等同于window.a = 2,我们知道将值分配给属性会返回分配的值。


但是在 REPL 上下文中,var a=2 也等同于 window.a=2(如果您的 REPL 是基于浏览器的,因为 window 对象本身就是全局对象)。 - Lee Kowalkowski
你走在正确的道路上,但这是不正确的。它与全局对象无关。var a; ... a = 1;分配给一个本地变量,但a=1仍将返回1var语句总是返回空值;赋值表达式(无论是对本地已定义的变量还是对隐式全局变量)总是返回分配的值。 - josh3736

1

var a = 2 是一个语句。因此它没有值。


1
变量 does 不返回任何值,但并非因为它是一个语句。其他语句会返回值。例如:for(i = 0; i < 1; i++) {'hello'}; - Lee Kowalkowski

1
您正在评估一个语句列表。在评估语句列表时,将返回最后一个产生值的语句的值。请注意本节末尾的示例http://ecma-international.org/ecma-262/5.1/#sec-12.1。如果列表中没有语句返回值,则不会返回任何内容(在JavaScript中,这是undefined)。
变量语句不返回值http://ecma-international.org/ecma-262/5.1/#sec-12.2
赋值运算符会返回一个值(并执行赋值操作)http://ecma-international.org/ecma-262/5.1/#sec-11.13.1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接