小白随机在互联网上乱丢一些赛博垃圾,还望拨冗批评斧正。
要不要加分号?
先说结论:“不引起程序出错的前提下,加不加都可以,按自身习惯来。”
为什么JS可以不加分号?
实际上,行尾使用分号的风格来自于Java,也来自于C和C++,这一设计最初是为了降低编译器的工作负担。
但是,从今天的角度来看,行尾使用分号,其实是一种语法噪音,恰好JavaScript语言有提供了相对可用的分号自动补全规则,所以,很多JavaScript程序员都是倾向于不加分号的。
由于我是一个大二的萌新,此前只接触过C语言,所以个人编码习惯还是会在能加分号的地方都加上分号,目前为止这种编码习惯没有带来过什么麻烦。那么,为什么JS不像C语言一样非要老老实实加分号呢?
自动插入分号规则
自动插入分号规则独立于所有的语法产生式定义,规则有三条:
有换行符,且下一个符号是不符合语法的,那么就尝试插入分号。
有换行符,且语法中规定此处不能有换行符,那么就自动插入分号。
源代码结束处,不能形成完整的脚本或者模块结构,那么就自动插入换行符。
这样描述是比较难以理解的,我们一起看一些实际的例子进行分析。
let a = 1
void function(a){
console.info(a);
}(a)
在这个例子中,第一行结尾处有换行符,接下来 void 关键字接在 1 之后是不合法的,这里命中了我们的第一条规则,因此会在 void 前插入换行符。
var a = 1,b = 1, c = 1;
a
++
b
++
c
这也是个著名的例子,我们看到第二行的a之后,有换行符,后面遇到了++运算符,a后面跟++是合法的语法,但是事实上,在编译的时候,这里的 a 的后面会插入一个分号。所以这段代码最终的结果,b 和 c 都变成了2,而 a 还是1,引发了错误。那么,什么情况下JS不加分号会出错呢?
什么情况下不加分号会出错
1. 小括号开头的前一条语句
想说的一点是,为什么匿名函数前面要加分号;
假设:如果不加分号,程序最终编译成这样子:
var a = 4 console.log(a)(function () {...}
结果就会报错:Uncaught TypeError: console.log(...) is not a function
Why?
那是因为匿名函数是以括号()为开头,对于程序括号()代表函数执行,那前面应该就有函数名,编译后空格去掉就console.log(a)(...)
,自然报错。
这也是为什么JS语句后要加分号的原因。
那我不想在每条语句(console.log(a)
)后都加分号怎么办?
就需要在匿名函数前加分号,后面不加就前面加。
再来一条例子看看:这就是小括号开头的前一条语句要加分号。(匿名函数)
2. 中方括号开头的前一条语句
当然,解决方法就是在行首加分号。
3. 以 "(" ,"[" , "/" , "+" , "-" 开始的语句
以 "(" ,"[" , "/" , "+" , "-" 开始的语句,极有可能和前面一条语句一起解析。
如果前一条语句无法和后一条语句合并解析,JavaScript才会在第一条语句后插入分号,这是通用规则。
但是,有2个例外,
3.1 return ,break和continue
如果涉及 return 、break、continue 时,如果这三个关键字后紧跟换行,则该关键字后一定会插入分号;
return true
一定会被解析成
return; true;
这显然违背了代码的本意。
3.2 有 ”++“ 或 ”--“运算符时
如果涉及 ”++“ ,”--“运算符的时候,这些表达式可以作为表达式的前缀,也可以作为表达式的后缀。
如果将其作为表达式的后缀的话,它和表达式应该在同一行,否则,JavaScript会在行末添加添加分号,并且 ”++“ "--"会被作为下一句的前缀操作符与下一句一起解析。
x
++
y
这段代码解析为:
x; ++y;
看完这么多,我还是决定继续老老实实地给JS加分号了。。。