86

我遇到了 JavaScript 的“提升”,但我没有弄清楚这段代码是如何真正起作用的:

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}

b();
alert(a);

我知道像 ( function a() {}) 这样的函数声明将被提升到函数b范围的顶部,但它不应该覆盖的值a(因为函数声明覆盖变量声明而不是变量初始化)所以我希望警报的值会是 10 而不是 1!

4

5 回答 5

115
  1. 全局a设置为1
  2. b()叫做
  3. function a() {}被提升并创建一个局部变量a来掩盖全局a
  4. 本地a设置为10(覆盖函数a
  5. 全局a(仍然1)被警告
于 2013-03-09T13:26:06.253 回答
6

这是因为此示例中的编译/解释顺序有些误导。该function a () {}行在函数的任何其余部分执行之前被解释,所以在函数的最开始,a它的值是function a () {}. 当您将其重新分配给 时,您将在 function 的本地范围内10重新分配值,然后在您返回时将其丢弃,将原始值留在全局范围内。ab()a = 1

alert()您可以通过在适当的地方放置 s 或类似的东西来验证这一点,以查看a各个点的值是什么。

于 2013-03-09T13:35:05.220 回答
5

(1) JavaScript 没有块语句作用域;相反,它将是块所在的代码本地的。

(2) Javascript 在函数范围内声明变量,这意味着在函数中声明的变量在该函数中的任何位置都可用,甚至在它们被赋值之前

(3) 在函数体内,局部变量优先于同名的全局变量。如果你声明一个与全局变量同名的局部变量或函数参数,你实际上隐藏了全局变量

你的代码是一样的:(阅读评论

<script>
var a = 1;          //global a = 1
function b() {
    a = 10;         
    var a = 20;     //local a = 20
}
b();
alert(a);           //global a  = 1
</script>

参考:
(1)JavaScript变量作用域:
(2) Javascript提升的危险例子
(3)变量作用域

所以在你的代码中:

var a = 1;          //global a = 1  
function b() {
    a = 10;         
    return;
    function a() {} //local 
}
b();
alert(a);           //global a = 1  
于 2013-03-09T16:40:11.690 回答
2
  1. 首先提升函数声明function a(){},因此在本地范围内a创建。
  2. 如果您有两个同名变量(一个在全局另一个在本地),则局部变量始终优先于全局变量。
  3. 设置时a=10,您设置的是局部变量a,而不是全局变量。

因此,全局变量的值保持不变,你会得到,alerted 1

于 2014-05-17T13:30:17.750 回答
0

当我读到你做JavaScript Scoping and Hoisting的同一篇文章时,我也很困惑,因为作者从未展示过这两个开放示例代码在编译器中的解释。

这是您提供的示例,以及页面上的第二个示例:

var a = 1;
function b() {
    function a() {} // declares 'a' as a function, which is always local
    a = 10;
    return;
}
b();
alert(a);

这是页面上的第一个示例:

var foo = 1;
function bar() {
    var foo; // a new local 'foo' variable
    if (!foo) {
        foo = 10;
    }
    alert(foo);
}
bar();

希望这可以帮助

于 2013-11-06T05:30:28.460 回答