在编程语言中,基本都是使用分号(;)将语句分隔开。从感觉上讲,这可以增加代码的可读性和整洁性。
缺少分隔符(;),一条语句的结束就成了下一条语句的开始,而在JS中,如若语句各占独立一行,通常可以省略语句间的分号(;),当然,右花括号(})处和程序结尾处的分号(;)也是可以省略的。
JS解析器是自动在换行补充分号(;)的,但它不是在所有的换行处都自动补充(;)的。
解析器是遵循以下的的规则,即是在缺少了(;),就无法正确解析代码的时候,解析器才会填充。换言之,这家伙很懒,如果不是当前的语句无法和随后的非空格字符当成一个整体解析的话,它不会干填充(;)的活。
说到这里,我想从编程风格方面说下,一种是尽量不用(;),除非迫不得已,在任何可以省略(;)的地方都将其省略;一种是只要有机会,就用(;),以明确语句的结束。由于本人是C++出身的,早已经习惯了用分号结束语句,故此,我是偏向于第二种风格。无论那种风格的,都有必要去理解JS的解析规则,方便于去阅读使用他人的代码。
在阅读jQuery源码的时候,发现一个小东西神出鬼没,它就是(;)。因此,为确保阅读的流畅性,从JQuery中跳出来,折腾一下javascript中的语句结束分隔符(注:这自是个人理解中的称呼),下面简称javascript为JS。
下面由简入难
var a=1;var b=2;//因为是分行的语句,所以第一个分号(;)是可以省略的。
var x=1;var y=3;//这种书写格式,明显第一个分号不能省略
上面的代码中,JS解析器是自动在换行补充分号(;)的,但它不是在所有的换行处都自动补充(;)的。
解析器是遵循以下的的规则,即是在缺少了(;),就无法正确解析代码的时候,解析器才会填充。换言之,这家伙很懒,如果不是当前的语句无法和随后的非空格字符当成一个整体解析的话,它不会干填充(;)的活。
例如:
var ee=1example(e)//会解析为var e; e=1; example(e);
因为无法解析var e e,所有就在其换行处自动填充上(;)。
那么,问题来了,这些分隔规则会带来一些意想不到的状况。
例如:
var x = f(a+b).toString()//看似两独立的语句,实则被解析为var x=f(a+b).toString();
如果程序中没有f()函数,错误还算容易排查,但若有着f()函数,这...会造成巨大的困扰。
那么,在程序中,“(, {, [ ,\, +, - ”这些字符开始的语句,就存在以上的风险,尤其是“(”,"["开始的语句是较为常见的。故,我们会看到一些程序员在代码开始之前添加上分号(;)。
例如
1. var x=0 //这里省略分号
2.
3. ;[x,x+1,x+3].forEach(console.log)
4. //前面有了个分号,自然可以确保语句被正确的解析
凡事都有例外。js肯定也是。return 、break、continue就是特殊的。这三个家伙,如果后面紧跟换行,解析器一定会自动在后面填充分号(;)。
1. return
2. true
3. //会被自动填充分号,被解析为return;true;这种结果一定不是你想见到的,因为在调试的时候,基本不是被报错。
所以,在这三个特殊关键字表达式作用前后,须得注意换行问题。
最后,还有个歧义问题。看如下代码,
1. a
2. ++
3. b
4. //这时候,会被解析成什么样呢?
5. //a;++b;
6. //我想大概,本意是希望运行var a++;b;
在学习C++的时候,很讨厌一些题目,比如说 a=3;b=4;求++a+++b;其实结果不是一定的,因为有些编译器是左运算,而有些是右运算。我想这些题目大概是要告诫我们,在关于运算时,写的语句一定不能造成歧义,不然平台换了,结果也变了。
由彼及此,在JS中,有歧义的东西,不同的浏览器引擎也是要统一也是很艰难的。所以,如果能加些括号、标点,能让大家伙都看的懂。付出点代价是值得的。
注:a++的运行效率确实比a=a+1要高上一些。
综上,可选的分号。能省不要省。