如果在声明变量之前使用了变量,为啥不会抛出 ReferenceError?
Posted
技术标签:
【中文标题】如果在声明变量之前使用了变量,为啥不会抛出 ReferenceError?【英文标题】:Why is no ReferenceError being thrown if a variable is used before it’s declared?如果在声明变量之前使用了变量,为什么不会抛出 ReferenceError? 【发布时间】:2016-05-30 03:29:07 【问题描述】:我正在努力思考 javascript 中引发的引用错误的行为。
在下面的例子中,ReferenceError
在第二行被抛出,执行中断:
var obj = ;
obj.func1 = func2;
alert('Completed');
而在本例中,代码成功完成,尽管obj.func1
仍然是undefined
:
var obj = ;
obj.func1 = func2;
var func2 = function()
alert('func2');
;
alert('Completed');
我的假设是同样会在第二行引发错误,如果不是这种情况,我本来希望 obj.func1
正确引用 func2
,但我已经加倍了盲目的。那么这里到底发生了什么?
【问题讨论】:
Function Hoisting 和 Variable Hoisting @epascarello:没有函数表达式的函数提升;只有函数 statements 被提升。这是var
吊装。
【参考方案1】:
var
被吊起;该变量存在于整个当前范围内。因此,第二个例子等价于:
var obj;
var func2;
obj = ;
obj.func1 = func2;
func2 = function()
alert('func2');
alert('Completed');
因此,当您执行分配时,名称 func2
是已知的,但 undefined
。在第一个例子中,它是未知的,它引发了ReferenceError
。
【讨论】:
【参考方案2】:这是由于 Javascript 变量声明“提升”。
用var
声明的变量在函数中随处可见,因此没有Reference Error
。但是,在您执行初始化它的语句之前,它实际上并没有收到它的值。所以你的第二个例子相当于:
var func2;
var obj = ;
obj.func1 = func2;
func2 = function()
alert('func2');
;
alert('Completed');
在这个重写中,当你对obj.func1
进行赋值时,你可以看到变量存在。但是由于它还没有值,所以您将undefined
分配给obj.func1
。稍后分配给func2
不会改变这一点。
【讨论】:
obj
的初始化与它的声明有什么关系?我理解,因为无论如何它都会立即发生,没有实际区别,但这是直译吗?
他直到 obj
被初始化后才引用它,因此在声明期间或之后初始化它实际上没有区别。所以我没有费心重写那部分,因为它与问题无关。
我想我只是担心你的例子是否有点模糊了行为,如果这个想法是 declarations 专门被提升。
只有在声明之前尝试使用变量时,声明和初始化之间的区别才有意义。如果所有的用途都在后面,没有区别,所以没有必要显示重写。【参考方案3】:
您的 func2 变量不可见。这就是 obj.func1 保持未定义的原因。
var obj = ;
var func2 = function()
alert('func2');
return "Test";
;
obj.func1 = func2;
alert('Completed');
【讨论】:
我很清楚在分配func1
之前定义 func2
会解决错误。这不是一个真正的问题,只是我在修修补补时发现的一些奇怪的东西。以上是关于如果在声明变量之前使用了变量,为啥不会抛出 ReferenceError?的主要内容,如果未能解决你的问题,请参考以下文章
为啥@interface 中声明的变量中的值不会在 XCTest 中的方法之间持续存在?
为啥不能在用 let 和 const 声明变量之前进行赋值? [复制]