2013-06-04 52 views
18

在爲javascript賦值之前需要聲明變量時,是否有類似的最佳做法?由於範圍原因,有時它是必要的,但如果範圍並不重要呢?聲明空javascript變量的最佳做法

// Declare first 
(function() { 
    var foo = 'bar', 
     a = 500, 
     b = 300, 
     c; 

    // Some things get done here with a and b before c can use them... 

    c = a * b;  

    // c is now ready to use... 
    doSomething(c); 
}()); 

// Declare when needed 
(function() { 
    var foo = 'bar', 
     a = 500, 
     b = 300; 

    // Some things get done here with a and b before c can use them... 

    var c = a * b; 

    // c is now ready to use... 
    doSomething(c); 
}()); 

而且我也想知道什麼是類似與對象文本的東西最好的做法:

// Add property with null assigned to it 
var myObj = { 
    foo: null, 

    doSomething: function() { 
     this.foo = 'bar'; 
    } 
}; 

// Property gets added when value is set 
var myObj = { 
    doSomething: function() { 
     this.foo = 'bar'; 
    } 
}; 
+1

大部分只是一個風格問題。 Crockford建議在範圍頂部聲明所有變量,它有時可以幫助清除一些常見的誤解(例如'for'循環內的'var'聲明,它實際上屬於'for'範圍之外的範圍)。 –

+0

@FabrícioMatté謝謝!甚至沒有想過'for'循環,但它確實有道理。 – Hendrik

回答

17

它基本上是一個風格問題。

由於var聲明是自動hoisted up的範圍的頂端,是有意義的把它們放在其範圍的頂部,這樣就可以讀取的代碼更接近解釋將如何執行它。

在範圍頂部聲明變量是Crockford's recommendation。它清除了一些常見的誤解,確實很有意義。

例如:

for (var i = 0; i < 3; i++) { 
    setTimeout(function() { 
     console.log(i); 
    }, 0); 
} 

由於var具有功能範圍,所有迭代(和它們的功能的內部)是指相同的i。由於所有三個定時功能都將在循環結束後執行,以上片段記錄了三次3

現在對於那些具有塊範圍經驗的人來說,上述行爲不是很清楚。重寫代碼片段:現在

var i; 
for (i = 0; i < 3; i++) { 
    // ... 
} 

i在全球範圍內被聲明,正如以前的片段。但是,這個更清晰。


另一個誤解:

(function() { 
    if (true) { 
     var foo = 1; 
    } else { 
     var foo = 1; 
    } 
}()); 

再次地,在塊作用域languages¹上面是完全有效的。然而,如var聲明吊起到在分析時的當前功能範圍的頂部,在上述等效於:

(function() { 
    var foo; 
    var foo; 
    if (true) { 
     foo = 1; 
    } else { 
     foo = 1; 
    } 
}()); 

的變量聲明兩次。大多數瀏覽器會忽略第二個聲明並且代碼將「工作」,但靜態代碼分析工具(例如JSHint)會對您大喊。

你可以只用一個聲明改寫它,它是完全有效的:

(function() { 
    if (true) { 
     var foo = 1; 
    } else { 
     foo = 1; 
    } 
}()); 

但是強迫症般的程序員和我一樣會發現它比較難看。所以再次聲明在範圍之上:

(function() { 
    var foo; 
    if (true) { 
     foo = 1; 
    } else { 
     foo = 1; 
    } 
}()); 

看起來更加整齊。


同樣,它主要是風格問題。就個人而言,如果我有一個巨大的功能,我討厭一直向上滾動來檢查一個變量是否已經聲明並將其添加到列表中。在這種情況下,我可以在函數中間添加幾個var聲明(針對克羅克福德的推薦),我個人發現它更易於閱讀和維護。

由於這是一個風格問題,所以請務必保持代碼的可維護性和簡潔性。


在硬幣的另一面,我承認,就個人而言,我已經開始和主要用於var聲明當變量首先使用。這是該語言的一個方面,您可以毫無問題地以這種方式使用它。但是我也會承認,如果我從一開始就遵循了Crockford的建議,那麼我會少了很多麻煩(就像上面顯示的錯誤概念一樣),並且會更快地掌握JavaScript的函數範圍方面。


¹需要注意的是JS 1.7引入了塊作用域的變量通過let,但沒有得到廣泛的被支持。

+0

爲了不讓問題的其他方面過於個人化,我會評論我自己的代碼不是最具可讀性的。雖然在一個團隊項目中工作時,嘗試定義一些乾淨合理的標準,確保代碼達到這些標準 - 這將提供更高的可維護性。 –