尽管 Javascript
有类似 C
的句法风格,但是它并不强制在代码中使用分号,所以分号可能被省略。Javascript
并不是一个缺少分号的语言,实际上,它需要分号来解析代码。因此当 Javascript
解析器遇到缺少分号而导致错误时会自动插入分号。
var foo = function() {
} // parse error, semicolon expected
test()
此时 Javascript
会自动插入分号,解析器将再次尝试。
var foo = function() {
}; // no error, parser continues
test()
自动的分号插入被认为是 Javascript
设计的缺陷之一,因为它能改变代码的行为。
工作原理
下面的代码没有分号,因此 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) {
// Not inserted, lines got merged
log('testing!')(options.list || []).forEach(function(i) {
}); // <- inserted
options.value.test(
'long string to pass here',
'and another long string to pass'
); // <- inserted
return; // <- inserted, breaks the return statement
{ // treated as a block
// a label and a single expression statement
foo: function() {}
}; // <- inserted
}
window.test = test; // <- inserted
// The lines got merged again
})(window)(function(window) {
window.someLibrary = {}; // <- inserted
})(window); //<- inserted
很明显,解析器插入分号后已经改变了代码原本的行为。
前置小括号
在有前置小括号的情形时,解析器将不会自动插入分号 。
log('testing!')
(options.list || []).forEach(function(i) {})
代码将被解析器转换为一行:
log('testing!')(options.list || []).forEach(function(i) {})
总结
基于以上研究,强烈建议在书写 Javascript
代码的时候不要省略分号,同时也建议大括号应该与对应的表达式处于同一行,即使 if else
语句只有一句也尽量不要省略大括号。这不仅将保证代码整体的一致性,也将有效地避免 Javascript
解析器对代码行为的错误改变。
对于是否省略 Javascript
分号,@barretlee 有篇博文写的很好,尤其是其中的一些例子举得很有代表性:
JavaScript Garden
接下来一章节介绍 delete
操作符,由于之前我自己已经研究过 delete
相关机制 - 《Javascript - Delete 机制》。因此我不打算再重复总结一篇博文。
参考
http://bonsaiden.github.io/JavaScript-Garden/#core.semicolon
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。