Appearance
自动插入分号规则
- 要有换行符,且下一个符号是不符合语法的,那么就尝试插入分号。
- 有换行符,且语法中规定此处不能有换行符,那么就自动插入分号。
- 源代码结束处,不能形成完整的脚本或者模块结构,那么就自动插入分号。
let a = 1
void function(a){
console.log(a);
}(a);
第一行插入分号,因为要有换行符,且下一个符号是不符合语法的
var a = 1, b = 1, c = 1;
a
++
b
++
c
结果在 a 后面插入分号, a;++b;++c,这是因为[no LineTerminator here]规则影响的
(function(a){
console.log(a);
})()
(function(a){
console.log(a);
})()
这段代码意图上显然是形成两个 IIFE。
我们来看第三行结束的位置,JavaScript 引擎会认为函数返回的可能是个函数,那么,在 后面再跟括号形成函数调用就是合理的,因此这里不会自动插入分号。这是一些鼓励不写分 号的编码风格会要求大家写 IIFE 时必须在行首加分号的原因。
不写分号需要注意的情况
以括号开头的语句
(function(a){
console.log(a);
})()/*这里没有被自动插入分号*/
(function(a){
console.log(a);
})()
这段代码看似两个独立执行的函数表达式,但是其实第三组括号被理解为传参,导致抛出错 误。
以数组开头的语句
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)
这段代码本意是声明三个变量,然后测试一个字符串中是否含有字母 a,但是因为没有自动 插入分号,正则的第一个斜杠被理解成了除号,后面的意思就都变了。
以 Template 开头的语句
var f = function(){
return "";
}
var g = f/*这里没有被自动插入分号*/
`Template`.match(/(a)/);
console.log(RegExp.$1)
这段代码本意是声明函数 f,然后赋值给 g,再测试 Template 中是否含有字母 a。但是因 为没有自动插入分号,函数 f 被认为跟 Template 一体的,进而被莫名其妙地执行了一次 。