据我了解,Javascript 不会编译,它只会运行。所以应该没有编译时错误,只有运行时错误。那么为什么这段代码不起作用?
function show() { console.log(x); }
(function () {
var x = 42;
show();
})()
我的问题不在于如何使这段代码更好;我意识到这是错误的代码,并且我已经知道如何修复它(见下文)。
我的问题是,为什么我会收到一个Uncaught ReferenceError
?如果 Javascript 仅在运行时抛出错误,它应该在调用匿名函数内部的 show()
时知道 x == 42
,对吗?
工作代码:
(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 中注册,引擎得到一个,然后 42 被分配给它。
现在这部分:
function show() { console.log(x); }
当调用 show 时,引擎首先为 x 询问 show 函数的作用域,因为它没有任何变量注册为名称 x,为 x 询问全局作用域(右值引用),因为它从未在全局注册scope 要么在编译阶段,它在任何范围内都找不到,我们得到引用错误。
it should know that x == 42 at the time it calls show(), which is inside the anonymous function, correct?
由于作用域规则,外部作用域中的变量在内部作用域中是可见的,反之亦然。 IIFE 内部的 x
在 IIFE 级别可见,而在外部范围内不可见。
关于javascript - 使用 undefined reference 运行函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43835595/