自動分號插入
儘管 JavaScript 有 C 的代碼風格,但是它不強制要求在代碼中使用分號,實際上可以省略它們。
JavaScript 不是一個沒有分號的語言,恰恰相反上它需要分號來就解析原始碼。
因此 JavaScript 解析器在遇到由於缺少分號導致的解析錯誤時,會自動在原始碼中插入分號。
var foo = function() {
} // 解析錯誤,分號丟失
test()
自動插入分號,解析器重新解析。
var foo = function() {
}; // 沒有錯誤,解析繼續
test()
自動的分號插入被認為是 JavaScript 語言最大的設計缺陷之一,因為它能改變代碼的行為。
工作原理
下面的代碼沒有分號,因此解析器需要自己判斷需要在哪些地方插入分號。
(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)
下面是解析器"猜測"的結果。
(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; // <- 插入分號, 改變了 return 運算式的行為
{ // 作為一個程式碼片段處理
foo: function() {}
}; // <- 插入分號
}
window.test = test; // <- 插入分號
// 兩行又被合并了
})(window)(function(window) {
window.someLibrary = {}; // <- 插入分號
})(window); //<- 插入分號
注意: JavaScript 不能正確的處理 return 運算式緊跟分行符號的情況,
雖然這不能算是自動分號插入的錯誤,但這確實是一種不希望的副作用。
解析器顯著改變了上面代碼的行為,在另外一些情況下也會做出錯誤的處理。
前置括弧
在前置括弧的情況下,解析器不會自動插入分號。
log('testing!')
(options.list []).forEach(function(i) {})
上面代碼被解析器轉換為一行。
log('testing!')(options.list []).forEach(function(i) {})
log 函數的執行結果極大可能不是函數;這種情況下就會出現 TypeError 的錯誤,詳細錯誤資訊可能是 undefined is not a function。
結論
建議絕對不要省略分號,同時也提倡將花括弧和相應的運算式放在一行,
對於只有一行代碼的 if 或者 else 運算式,也不應該省略花括弧。
這些良好的編程習慣不僅可以提到代碼的一致性,而且可以防止解析器改變程式碼為的錯誤處理。