ref:《重学前端》
我们写代码要不要写分号?
自动插入分号规则
- 要有换行符,且下一个符号是不符合语法的,那么就尝试插入分号。
- 有换行符,且语法中规定此处不能有换行符,那么就自动插入分号。
- 源代码结束处,不能形成完整的脚本或者模块结构,那么就自动插入分号。
let a = 1
void function(a){
console.log(a);
}(a);
第一行后有换行符,接下来 void 跟在 1 之后是不合法的,所以第一条规则符合插入换行符;
var a = 1, b = 1, c = 1;
a
++
b
++
c
第二行 a 之后有换行符,后面有 ++ 运算符,a 后面跟着 ++ 是合法的,按理说插入换行符,ab 为 2,c 等于 1,但是实际上结果却是 bc 为 2,a 是 1,因为下面提到的[no LineTerminator here]
UpdateExpression[Yield, Await]:
LeftHandSideExpression[?Yield, ?Await]
LeftHandSideExpression[?Yield, ?Await][no LineTerminator here]++
LeftHandSideExpression[?Yield, ?Await][no LineTerminator here]--
++UnaryExpression[?Yield, ?Await]
--UnaryExpression[?Yield, ?Await]
(function(a){
console.log(a);
})()
(function(a){
console.log(a);
})()
上面是两个 IIFE 立即执行函数表达式,我们看第三行 () 结束,js 引擎认为函数返回的可能是个函数,那么后面再跟上括号则形成了函数的调用,那么也是合理的,所以也应该换行符,但是实际上这么运行是会报错的。所以在 IIFE 函数时必须再行首加分号的原因就是因此。
function f(){
return/*
This is a return value.
*/1;
}
f();
在这 return 和 1 被注释分开了。根据 JavaScript 自动插入分号规则,带换行符的注释也被认为是有换行符,return 同样也有 [no LineTerminator here] 规则要求。所以这里 return 后会自动插入分号,返回是 undefined。
no LineTerminator here 规则
[no LineTerminator here] 规则表示它所在的结构中的这一位置不能插入换行符。
下图列出了所有标准中的规则。

所以上面 ++ -- 后自增和后自减运算符为什么插入换行符就知道为什么了。
不写分号需要注意的情况
以括号开头的
(function(a){
console.log(a);
})()/* 这里没有被自动插入分号 */
(function(a){
console.log(a);
})()
所以 IIFE 函数要注意。
以数组开头的语句
var a = [[]]/* 这里没有被自动插入分号 */
[3, 2, 1, 0].forEach(e => console.log(e))
这段代码本意是一个变量 a 赋值,然后对一个数组执行forEach,但是因为没有自动插入分号,被理解为下标运算符和逗号表达式,不会抛出错误。
以正则表达式开头的语句
var x = 1, g = {test:()=>0}, b = 1/* 这里没有被自动插入分号 */
/(a)/g.test("abc")
console.log(RegExp.$1)
正则的第一个斜杠被理解成了除号,后面的意思就都变了
以Template开头的语句
var f = function(){
return "";
}
var g = f/* 这里没有被自动插入分号 */
`Template`.match(/(a)/);
console.log(RegExp.$1)
我们写代码要不要写分号?
自动插入分号规则
第一行后有换行符,接下来 void 跟在 1 之后是不合法的,所以第一条规则符合插入换行符;
第二行 a 之后有换行符,后面有 ++ 运算符,a 后面跟着 ++ 是合法的,按理说插入换行符,ab 为 2,c 等于 1,但是实际上结果却是 bc 为 2,a 是 1,因为下面提到的[no LineTerminator here]
上面是两个 IIFE 立即执行函数表达式,我们看第三行 () 结束,js 引擎认为函数返回的可能是个函数,那么后面再跟上括号则形成了函数的调用,那么也是合理的,所以也应该换行符,但是实际上这么运行是会报错的。所以在 IIFE 函数时必须再行首加分号的原因就是因此。
在这 return 和 1 被注释分开了。根据 JavaScript 自动插入分号规则,
带换行符的注释也被认为是有换行符,return 同样也有 [no LineTerminator here] 规则要求。所以这里 return 后会自动插入分号,返回是 undefined。no LineTerminator here 规则
[no LineTerminator here] 规则表示它所在的结构中的这一位置不能插入换行符。
下图列出了所有标准中的规则。

所以上面 ++ -- 后自增和后自减运算符为什么插入换行符就知道为什么了。
不写分号需要注意的情况
以括号开头的
所以 IIFE 函数要注意。
以数组开头的语句
这段代码本意是一个变量 a 赋值,然后对一个数组执行forEach,但是因为没有自动插入分号,被理解为下标运算符和逗号表达式,不会抛出错误。
以正则表达式开头的语句
正则的第一个斜杠被理解成了除号,后面的意思就都变了
以Template开头的语句