2010-04-28 46 views
10

退房的HTML/Javascript代碼下面的代碼片段:for()循環中聲明的Javascript變量的作用域是什麼?

<html> 
<head> 
<script type="text/javascript"> 
var alerts = []; 
for(var i = 0; i < 3; i++) { 
    alerts.push(function() { document.write(i + ', '); }); 
} 

for (var j = 0; j < 3; j++) { 
    (alerts[j])(); 
} 

for (var i = 0; i < 3; i++) { 
    (alerts[i])(); 
} 
</script> 
</head><body></body></html> 

此輸出:

3, 3, 3, 0, 1, 2 

這不是我所期待的 - 我期待輸出0, 1, 2, 0, 1, 2,

我(錯誤地)認爲被推入到數組中的匿名函數會表現爲閉包,捕獲創建函數時分配的值i - 但它實際上似乎是i表現爲全局變量。

任何人都可以解釋這個代碼示例中i的範圍發生了什麼,以及爲什麼匿名函數沒有捕獲它的值?

回答

6

在Javasript中,唯一「有趣」的詞彙範圍邊界是函數體。在函數中任何地方聲明的任何東西(以及除另一個嵌套函數以外的任何地方)都處於相同的範圍。關於解釋聲明的方式也有一些奇怪的事情。

您的匿名函數確實充當閉包,但實例化的每個函數將共享相同的「我」。我用一個小竅門是添加的功能另一層:

for (var i = 0; i < whatever; i++) { 
    (function(idaho) { 
    whatever(function() { alert("my own private " + idaho); }); 
    })(i); 
} 

在somepoint希望所有的瀏覽器將支持新的「讓」的聲明,這是一個短,少看起來怪怪的方式基本上做同樣的事情。

8

範圍是變量定義的函數(除了沒有一個,所以它是全局的)。

您傳遞的匿名函數正在訪問在父函數(又是全局)範圍中定義的變量。

您需要實際關閉。

alerts.push(
    function (foo) { 
     return function() { 
      document.write(foo + ', '); 

     } 
    }(i) 
); 
+0

正確答案 - 謝謝! - 但我接受了Pointy的回答,因爲「我自己的私人」+愛達荷讓我大聲笑出聲來...... – 2010-04-28 22:14:07

相關問題