2011-08-26 117 views
5

由于我是一个JavaScript新手,我开始学习它,但我刚刚开始就陷入了困境。 我正在关注a Mozilla Tutorial,并且我在JavaScript中遇到了变量作用域的问题。我有一些代码:可变范围问题

var myvar = "my value"; 

var zmienna = "string"; 

(function() { 
    alert(myvar); 
    alert(zmienna); 
})(); 

(function() { 
    alert(myvar); // undefined 
    var myvar = "local value"; 
    alert(zmienna); 
})(); 

在教程中,我读过JavaScript变量在功能块中不可见。那么,前两个警报说的是正确的值。这很奇怪,因为第三次警报显示“未定义”,尽管事实上前面的功能块没有任何变化。第四个,再次,打印正确的价值。

有人可以解释我,这里发生了什么?我会很高兴,因为教程没有提到更多。

+0

_“我读过的JavaScript变量不可见功能块“。_教程中的内容在哪里?那句话没有意义。 –

回答

1

“我读过JavaScript变量在功能块中不可见”。

这并不完全正确。它们可以从嵌套函数中获得。

嵌套函数创建一个范围链。在另一个函数中创建的函数可以访问自己的变量以及嵌套函数的变量。

功能的可看到函数B的变量,如果函数A没有嵌套功能B.

var myvar = "my value"; // <-- global variable, seen by all functions  
var zmienna = "string"; // <-- global variable, seen by all functions 

(function() { 
    alert(myvar); // <-- referencing the global variable 
    alert(zmienna); // <-- referencing the global variable 
})(); 
(function() { 
    // v--- Declaration of these "local" variables were hoisted to the top... 
    // var myvar; // <--- ...as though it was here. 
    // var new_var; // <--- ...as though it was here. 

    alert(myvar); // undefined (myvar is delcared, but not initialized) 
    alert(new_var); // undefined (new_var is delcared, but not initialized) 

    var myvar = "local value"; // <-- assign the value 

    alert(zmienna); // <-- referencing the global variable 
    alert(myvar); // <-- referencing the local variable 

    var new_var = "test"; // <-- another new local variable 

    // A nested function. It has access to the variables in its scope chain. 
    (function() { 
     alert(myvar); // <-- referencing the variable from its parent func 
     alert(new_var); // <-- referencing the variable from its parent func 
    })(); 
})(); 
/* 
Here's a new function. It was not nested inside the previous function, so it 
    has access to the global variables, and not the locals of the previous func 
*/ 
(function() { 
    alert(myvar); // <-- referencing the global variable 
    alert(new_var); // <-- ReferenceError 
})(); 
+0

非常感谢您的回答。现在看来是合乎逻辑的。虽然,我必须承认,对我来说,Javascript对于我有一些知识的其他语言(主要是C++,PHP和Erlang)来说要困难得多。再次感谢你。 – Radi

+0

@Radi:不客气。我对Erlang有一些了解,但对其他两位不了解。这种现象被称为* shadowing *,其中嵌套函数可以在其父项中声明一个与变量名称相同的变量,因此您得到的值取决于您所处的范围链的哪个级别,因为嵌套块访问祖先的人。如果我记得,由于打字强烈,Erlang不允许阴影,但我可能没有正确记住。 – user113716

+0

嗯,说实话,虽然编译器会警告你(可以查看:https://gist.github.com/1173877) – Radi

9

使用var已悬挂。

由于您在函数内部有var myvar,因此存在本地范围myvar。由于您在发出警报后为其分配了一个值,因此在您发出警报时它是undefined

+0

好的,谢谢。但为什么前两个警报显示正确的价值,尽管教程说不同(据我了解,应该是“未定义”,因为他们在不同的范围)。你能解释我吗? – Radi

+1

因为您在全局范围内声明了'myvar'和'zmienna'。所以他们可以从脚本中的任何地方访问,如果没有被本地范围定义隐藏的话。 – J0HN

+0

@Quentin:可能会向OP显示等价代码,向初学者展示“悬挂”的含义以及如何提升声明,但是分配不是。 – user113716