盡管 JavaScript 有 C 的代碼風(fēng)格,但是它不強(qiáng)制要求在代碼中使用分號(hào),實(shí)際上可以省略它們。
JavaScript 不是一個(gè)沒有分號(hào)的語言,恰恰相反上它需要分號(hào)來就解析源代碼。 因此 JavaScript 解析器在遇到由于缺少分號(hào)導(dǎo)致的解析錯(cuò)誤時(shí),會(huì)自動(dòng)在源代碼中插入分號(hào)。
var foo = function() {
} // 解析錯(cuò)誤,分號(hào)丟失
test()
自動(dòng)插入分號(hào),解析器重新解析。
var foo = function() {
}; // 沒有錯(cuò)誤,解析繼續(xù)
test()
自動(dòng)的分號(hào)插入被認(rèn)為是 JavaScript 語言最大的設(shè)計(jì)缺陷之一,因?yàn)樗?em>能改變代碼的行為。
下面的代碼沒有分號(hào),因此解析器需要自己判斷需要在哪些地方插入分號(hào)。
(function(window, undefined) {
function test(options) {
log('testing!')
(options.list || []).forEach(function(i) {
})
options.value.test(
'long string to pass here',
'and another long string to pass'
)
return
{
foo: function() {}
}
}
window.test = test
})(window)
(function(window) {
window.someLibrary = {}
})(window)
下面是解析器"猜測(cè)"的結(jié)果。
(function(window, undefined) {
function test(options) {
// 沒有插入分號(hào),兩行被合并為一行
log('testing!')(options.list || []).forEach(function(i) {
}); // <- 插入分號(hào)
options.value.test(
'long string to pass here',
'and another long string to pass'
); // <- 插入分號(hào)
return; // <- 插入分號(hào), 改變了 return 表達(dá)式的行為
{ // 作為一個(gè)代碼段處理
foo: function() {}
}; // <- 插入分號(hào)
}
window.test = test; // <- 插入分號(hào)
// 兩行又被合并了
})(window)(function(window) {
window.someLibrary = {}; // <- 插入分號(hào)
})(window); //<- 插入分號(hào)
注意: JavaScript 不能正確的處理
return表達(dá)式緊跟換行符的情況, 雖然這不能算是自動(dòng)分號(hào)插入的錯(cuò)誤,但這確實(shí)是一種不希望的副作用。
解析器顯著改變了上面代碼的行為,在另外一些情況下也會(huì)做出錯(cuò)誤的處理。
在前置括號(hào)的情況下,解析器不會(huì)自動(dòng)插入分號(hào)。
log('testing!')
(options.list || []).forEach(function(i) {})
上面代碼被解析器轉(zhuǎn)換為一行。
log('testing!')(options.list || []).forEach(function(i) {})
log 函數(shù)的執(zhí)行結(jié)果極大可能不是函數(shù);這種情況下就會(huì)出現(xiàn) TypeError 的錯(cuò)誤,詳細(xì)錯(cuò)誤信息可能是 undefined is not a function。
建議絕對(duì)不要省略分號(hào),同時(shí)也提倡將花括號(hào)和相應(yīng)的表達(dá)式放在一行,
對(duì)于只有一行代碼的 if 或者 else 表達(dá)式,也不應(yīng)該省略花括號(hào)。
這些良好的編程習(xí)慣不僅可以提到代碼的一致性,而且可以防止解析器改變代碼行為的錯(cuò)誤處理。