1

尽管 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分号,加还是不加?》

JavaScript Garden 接下来一章节介绍 delete 操作符,由于之前我自己已经研究过 delete 相关机制 - 《Javascript - Delete 机制》。因此我不打算再重复总结一篇博文。

参考

http://bonsaiden.github.io/JavaScript-Garden/#core.semicolon


StephenLi
7k 声望488 粉丝

知不足。