2014-01-14 17 views
12

JavaScript只有函數範圍。因此,在for循環中聲明的變量對於整個函數是可見的。處理在多個for循環中聲明的變量的最習慣的方法是什麼?

例如,

function foo() { 
    for(var i = 0; i < n; i++) { 
     // Do something 
    } 
    // i is still in scope here 
} 

當我們有多個for循環,這打開了我們如何處理這些其他變量的for循環的問題。

我們是否使用不同的變量?

for(var i = 0; i < n; i++) { } 
for(var j = 0; j < n; j++) { } 

或者我們使用相同的變量,但只是分配一個值(而不是聲明它)?

for(var i = 0; i < n; i++) { } 
for(i = 0; i < n; i++) { } 

或者聲明i以外的循環?

var i; 
for(i = 0; i < n; i++) { } 
for(i = 0; i < n; i++) { } 

或redeclare i

for(var i = 0; i < n; i++) { } 
for(var i = 0; i < n; i++) { } 

所有這些工作(或至少他們在我的瀏覽器的最新版本上)。雖然,JSHint不喜歡最後一種方法。

有沒有一種最習慣的方法?

+1

我會使用最後兩個之一。儘管JSHint的投訴,我喜歡最後一個;如果我必須保持沉默,我會使用前一個。 – Barmar

+4

爲了記錄,JavaScript正在獲得塊範圍。所以,今後,你還會['for(let i ...)'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let),它會將'i'聲明爲循環的本地。 –

+1

我更喜歡在兩個循環之外聲明'i'(但不一定在函數的頂部 - 請不要將它們全部放在一行/逗號分隔的位置),但是如果您發現自己正在執行此操作太多了,也許你需要更多的功能? – Ryan

回答

3

這實際上取決於你是誰編碼。如果你正在爲公司編碼或爲圖書館做出貢獻,你當然會遵循他們的風格指南。我已經看到了所有這些(期待最後)在庫中使用。如果你喜歡道格拉斯克羅克福德式的風格,你可以倒數第二,把所有的變量放在函數範圍的頂部(否則jslint會對你大喊)。

以一個例子來自jQuery style guide

這被認爲是良好的樣式

var i = 0; 

if (condition) { 
    doSomething(); 
} 

while (!condition) { 
    iterating++; 
} 

for (; i < 100; i++) { 
    object[ array[ i ] ] = someFn(i); 
} 

雖然這是差風格

// Bad 
if(condition) doSomething(); 
while(!condition) iterating++; 
for(var i=0;i<100;i++) object[array[i]] = someFn(i); 

無論如何,因爲這是風格我將參考幾個庫爲每個庫編寫它們的方式哎呀:

如果你的代碼將被最小化,你放開它之前,都不會有問題的minifiers將裂傷它幾乎同一端的處理表示。

+0

他們建議在聲明時初始化'i',而不是在for循環的初始化部分? :( –

3

使用不同的變量我們沒有問題。

重複使用和重新分配會使代碼更不可讀,如果我們稍後再刪除聲明,我們就會冒險將i分配給函數作用域之外的某個東西。

聲明我在循環外,我們沒有問題。

如果你的lint工具,IDE等抱怨,重新聲明將是一個問題。

所以我會爭取第一個或第三個選項。如果使用第一個選項關注變量的數量,那麼您可能需要重構。

1

在函數中聲明的任何變量都被解釋爲在函數的開頭聲明。 Doug Crockford認爲你應該在每個函數的第一行聲明所有的變量。

doSomething = function() { 
    var i, ... other variables ...; 
    ... 
    for (i = 0; i < x; i += 1) { 
     ... 
    } 
    ... 
    for (i = 0; i < x; i += 1) { 
     ... 
    } 
} 

這種方式的代碼讀取方式與javascript引擎分析的方式相同。

3

另一個需要以不同的方式回答問題。

多有圈的功能讓我懷疑這是因爲:

  1. 它可能會做太多,無論如何都應該被分解,
  2. 這可能是更好的它更功能編寫和消除指數共(它在某些each的可用 -/map -y功能反正)
3

另一種方法是使用迭代器的功能。例如,在現代瀏覽器的Array將有forEach方法:如果您在使用舊的瀏覽器(或自定義集合)

var items = ["one", "two", "three"]; 
var things = ["hello", "goodbye"]; 

items.forEach(function (item, index) { 
    // Do stuff 
}); 

things.forEach(function (item, index) { 
    // Do stuff 
}); 

,你可以讓你自己的迭代是這樣的:

Array.prototype.forEach = function(callback) {  
    for(var i = 0; i < this.length; i++) { 
     callback.apply(this, [this[i], i, this]); 
    } 
}; 

欲瞭解更多信息,請參閱:Array.prototype.forEach()

相關問題