2013-06-12 188 views
10

下面的代码是JavaScript代码。我正在尝试理解JavaScript中的函数范围,并且在here之后的文章之后。我正在复制下面的代码 -了解JavaScript函数范围

var cow = "purple"; // just a random cow 

var f = function (x) { 
    var r = 0; 
    cow = "glue"; 
    if (x > 3) { 
     var cow = 1; // a local variable 
     r = 7; 
    } 
    return r; 
}; 

var z = f(2); 
alert(cow); // returns purple 

我不太明白为什么字符串“紫色”被警告。 cow = "glue";行应该将cow变量的值设置为“glue”。如果我删除了if块,然后在最后一条语句中警告牛,我会看到字符串“glue”被警告。

当f(2)被调用时,if代码块没有被输入,也没有任何内容被执行,所以为什么我会看到不同的结果?即为什么在上一条语句中提醒母牛现在返回字符串“purple”?

回答

4

Javascript没有块范围(catch块除外)。
所有var语句都是悬挂到包含函数的顶部。

因此,cow引用函数中任何位置的局部变量,即使if从不执行。

+1

实际上,即使'catch'块都没有自己的作用域(*变量*环境)。请参阅[为什么catch子句有自己的*词法*环境?](http://stackoverflow.com/q/15034864/1048572) – Bergi

9

函数内部的变量声明总是被提升到顶部。所以,你的代码实际上是:

var f = function (x) { 
    var cow, r; 
    r = 0; 
    cow = "glue"; 
    if (x > 3) { 
     cow = 1; // a local variable 
     r = 7; 
    } 
    return r; 
}; 

在函数内部你总是分配给当地cow,从来都不是全球性的。

+0

我认为你的意思是'var cow,r' there,not'var f, r' –

+0

@ ben336是的,我修复了一段时间。也许你的浏览器没有得到编辑通知? websocket的东西有时会失败... – bfavaretto

+0

耶现在看到它。今天使用点状网络连接。也没有看到其他人回答,直到我发布我的。 –

5

这里要理解的两件事是,JavaScript变量被提升到其范围的顶部,并且JavaScript没有块范围。

所以

  1. 在范围内的所有变量都被认为在声明的范围
  2. 年初if语句不创建一个新的范围。

所以,你的例子是相当于

var cow = "purple"; // just a random cow 

var f = function (x) { 
    var cow, r = 0; 
    cow = "glue"; 
    if (x > 3) { 
     cow = 1; // a local variable 
     r = 7; 
    } 
    return r; 
}; 

var z = f(2); 
alert(cow); // returns purple 

if语句的VAR声明提升到顶部。此时,函数中的所有牛引用都指的是局部变量牛,而不是来自外部作用域的牛。

+0

本教程中没有var前面的cow = glue,我不知道这是否是作者的错误 – Ibu

+0

如果要显示js scope的工作方式,它不一定是错误。在if语句中声明一个var是不好的做法,因为它很容易混淆,但它并不是“错误的” –

+0

+1,因为它指出if语句块没有创建一个新的作用域,这很可能是OP误解的来源。 – bfavaretto

4

你没看过那篇文章,是吗?它明确规定

是否cow得到变成"glue"当你打电话f(2)?没有,cow在上面的代码中是安全的,因为var cow里面的if语句声明适用于整个函数。这意味着cow是整个函数的局部变量。

但是,当您删除if块时,还会删除其中的变量声明,并且该赋值将以全局变量为目标。