2013-08-31 178 views
5
for(var i = 0; i < 100; i++){ 
    var foo = 5; 

} 

它的工作原理...但這個壞?變量聲明多次

我知道我可以在外面聲明var foo,但爲什麼當我只打算在循環使用嗎?

+11

實際上,它只聲明一次。所有變量聲明都被提升到其作用域的頂部(函數的開頭或全局作用域)。塊不會在JavaScript中創建範圍。 – bfavaretto

+0

@bfavaretto:至少現在還沒有。 – elclanrs

+0

即使語義作爲bfavaretto描述,我更願意將「聲明關閉」到使用站點。這不會改變代碼的行爲方式,但*我發現*它使代碼的意圖更加清晰,我可以掃描代碼以查看是否有可疑的不合適的地方。其他人可能會不同意,這很好。 – user2246674

回答

3

隨着時間的推移我的個人風格已經成長爲一個偏愛宣稱,他們「實際上是」在我在工作的特定語言的「心」的變量。對於JavaScript,這意味着將變量和函數聲明中的位置,其中無論如何,這種語言會把他們提起來。

這是清晰,準確的溝通,理解,維護,以保持我自己的心理過程平行於語言的過程中,只提到了幾個很好的理由。

因此,在這種特殊情況下,我不會將var foo = 5;聲明放入for循環的主體中,原因很簡單,因爲它沒有做它看起來像它正在做的事情,即它實際上沒有重新聲明/每次迭代重新確定變量的範圍。 (將var聲明放在for循環標題的初始化部分(初始化;條件;事後考慮)會更合理,並且當然是將它放入具有塊級變量的語言的正確位置,例如JavaScript完成採用塊級範圍的let樣式聲明)

注:

  • 這種做法可能看起來並不「正常」。我的思想傾向於保持變量「接近」它們的使用,而我目前的做法並不自然地適應我的思維方式。但作爲一名程序員,多年來,混亂,錯誤的溝通,誤解,無法解開的不可維護的代碼等等的經驗不僅沒有證明我需要遵循這種在相應位置聲明變量的方式實際範圍,不管語言。

  • 這種做法對我來說有一個額外的好處,它鼓勵我保持我的功能模塊化和合理的大小。

  • 沿着同樣的道路,遵循這種做法自動地幫助保持我的代碼以合理的方式組織。例如,如果首先將我的函數放在實際工作的代碼之前,會導致出現過多的函數,並且因此我不得不下拉兩頁來編輯我的程序,這種方式會自動激發我組織我的編碼到不同文件的適當結構中。

P.S.有人可能會提出一些觀點,即某些函數太長,以至於這種做法會使變量聲明最終離開它們使用的地方。是的,我已經看到了代碼的真實性,甚至可能代碼無法幫助。然而,我不禁要看到散文作家同樣適用於計算機程序員的平行。隨着技能水平的提高,作者句子的長度(以及程序員功能的大小)往往會增長,然後隨着技能水平的不斷提高,句子的長度(以及程序員的函數的大小)往往會縮短一次更多。

+0

確保你的方法保持苗條,那麼你在這麼多地方不需要太多的變量。但是我更喜歡在他們使用的地方聲明變量,即使他們被吊起來了。 –

3

這是不好的,因爲它給人的假象,ifoo是局部變量。

for(var i = 0; i < 100; i++){ 
    var foo = 5; 
} 
foo; // 5 

這可能不是簡單的代碼中的問題,但如果你使用閉包很明顯,只有一個foo

var counters = []; 
for (var i = 0; i < 100; i++) { 
    var foo = 5; 
    counters.push(function() { foo++; return foo; }); 
} 
counters[0](); // 6 
counters[0](); // 7 
counters[1](); // 8 (!) 

要在不同的範圍內創建foo函數需要介紹:

var counters = []; 
for (var i = 0; i < 100; i++) { 
    (function() { 
     var foo = 5; 
     counters.push(function() { foo++; return foo; }); 
    })(); 
} 
counters[0](); // 6 
counters[0](); // 7 
counters[1](); // 6 

這裏是事情出錯,由於這是一個真實的例子:setTimeout in for-loop does not print consecutive values

從JavaScript 1.7開始,您可以使用let關鍵字(請參閱MDN)創建真正的局部變量。