我遇到了以下代码段:
(function() {
bar = 5;
var bar = 10;
console.log("value of bar inside the self invoking function = " + bar);
})();
console.log("value of bar out of function scope " + bar);

当我执行上面的代码时,我得到:
"未捕获的ReferenceError"
用于第二个控制台
答案 0 :(得分:6)
这是由于"变量提升"。在解析javascript时声明变量,因此在执行时,引擎已经知道范围内可用的所有变量,因此可以分配给它们。提升过程完成后,您的功能实际上就像这样。
(function() {
var bar;
bar = 5;
bar = 10;
console.log("value of bar inside the self invoking function = " + bar);
})();
console.log("value of bar out of function scope " + bar);

您可以在MDN上详细了解它:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting
答案 1 :(得分:0)
用var
声明的所有变量都被提升到声明它们的函数的顶部。因此,如果变量在函数内定义,它将被移动到函数的顶部,如果它被定义在全局范围内,它将被移到全局上下文的顶部。
(function() {
bar = 5;
var bar = 10;
console.log("value of bar inside the self invoking function = " + bar);
})();
在这种情况下,你已经在匿名函数中定义了变量,所以它将被移动到这个函数的顶部,并在提升之后就像是
(function() {
var bar;
bar = 5;
bar = 10;
//...rest of the code
})();
但是这个变量仅在该功能的本地范围中可用,它在全局范围内不可用。这就是为什么当您尝试在全局范围中访问它时Uncaught ReferenceError
。
这是一篇很好的文章,解释了JavaScript中的变量范围和变量提升。 http://javascriptissexy.com/javascript-variable-scope-and-hoisting-explained/
需要注意的是,只有使用var
声明的变量才会被提升。如果您使用ES6 let
关键字来声明变量,那么它将不会被提升。所以
(function() {
bar = 5;
let bar = 10;
console.log("value of bar inside the self invoking function = " + bar);
})();
不会工作,你会得到同样的错误。您可以阅读更多相关信息here