2011-08-26 85 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