据我了解,Javascript 不能编译,只能运行。所以应该没有编译时错误,只有运行时错误。那么为什么这段代码不起作用呢?
function show() { console.log(x); }
(function () {
var x = 42;
show();
})()
我的问题不在于如何使这段代码更好;我意识到这是糟糕的代码,我已经知道如何修复它(见下文)。
我的问题是,为什么我会得到UncaughtReferenceError
?如果 Javascript 只在运行时抛出错误,它应该知道x == 42
在它调用时show()
,匿名函数内部,对吗?
工作代码:
(function () {
var x = 42;
function show() { console.log(x); }
show();
})()
工作代码,最佳选择:
function show(y) { console.log(y); }
(function () {
var x = 42;
show(x);
})()
注意:下面的描述是从 ES5 开始的,而不是 ES6,因为 ES6 的作用域规则已经改变(由于引入了 let)。
Javascript 确实可以编译。只是像 c++/c# 等其他语言一样,没有像 exe/IL 代码这样的中间东西需要单击才能开始执行。在 JS 中,在编译阶段之后开始执行。
因此,当编译发生时,编译器会查找函数声明和var declaration
变量。因此对于这个 IIFE,
(function () {
var x = 42;
show();
})();
它确实找到了一个 var 声明,并且变量 x 注册在 IIFE 的范围内。这称为变量提升,x 在函数级别可用,在本例中为 IIFE。
稍后在执行时,IIFE 看起来像这样(概念上):
(function () {
//registration of x in this function's scope has already happened at
//compile time. Notice absence of `var`
x = 42;
show();
})();
现在,此时引擎与作用域对话并请求 x 的左值引用。由于 x 已在 IIFE 中注册,因此引擎获得 1,然后将 42 分配给它。
现在对于这部分:
function show() { console.log(x); }
当 show 被调用时,引擎首先询问 x 的 show 函数的作用域,因为它没有任何用名称 x 注册的变量,全局作用域被询问(右值引用)为 x,因为它从未在全局作用域中注册过编译阶段,在任何范围内都找不到它,我们得到引用错误。
it should know that x == 42 at the time it calls show(), which is inside the anonymous function, correct?
由于作用域规则,外部作用域中的变量在内部作用域中可见,反之亦然。x
inside IIFE 在 IIFE 级别可见,在外部范围之外不可见。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句