编程风格-行尾的分号

在 JavaScript 中,分号表示一个语句的结束。并且 JavaScript 允许省略行尾的分号。JavaScript 存在不使用分号的情况,但是有的情况省略分号会带有一些问题。

不使用分号的情况

1. for 和 while 循环

for ( ; ; ) {
} // 没有分号

while (true) {
} // 没有分号

do...while循环是有分号的

do {
  a--;
} while(a > 0); // 分号不能省略

2. 分支语句:if,switch,try

if (true) {
} // 没有分号

switch () {
} // 没有分号

try {
} catch {
} // 没有分号

3. 函数的声明语句

function f() {
} // 没有分号

注意,函数表达式仍然要使用分号。

var f = function f() {
};

以上三种情况,语法规定本来就不需要在结尾添加分号。 如果使用了分号,并不会出错。因为,解释引擎会把这个分号解释为空语句。

分号的自动添加

除了上面的三种情况,所有语句都应该使用分号。但是,如果没有使用分号, JavaScript 会自动添加。这种语法特性被称为“分号的自动添加” (ASI)。

var a = 1
// 等同于
var a = 1;

因此,就有很多人的整片代码都不会使用分号,是可以少很多字符。但麻烦的是,如果下一行的开始可以与本行的结尾连在一起解释,JavaScript 就不会自动添加分号。

// 等同于 var a = 3
var
a
=
3

// 等同于 'abc'.length
'abc'
.length

// 等同于 return a + b;
return a +
b;

// 等同于 obj.foo(arg1, arg2);
obj.foo(arg1,
arg2);

// 等同于 3 * 2 + 10 * (27 / 6)
3 * 2
+
10 * (27 / 6)

上面代码都会多行放在一起解释,不会每一行自动添加分号。下面这个例子就不那么容易看出来了

x = y
(function () {
  // ...
})();

// 等同于
x = y(function () {...})();

下面是更多不会自动添加分号的例子。

// 引擎解释为 c(d+e)
var a = b + c
(d+e).toString();

// 引擎解释为 a = b/hi/g.exec(c).map(d)
// 正则表达式的斜杠,会当作除法运算符
a = b
/hi/g.exec(c).map(d);

// 解释为'b'['red', 'green'],
// 即把字符串当作一个数组,按索引取值
var a = 'b'
['red', 'green'].forEach(function (c) {
  console.log(c);
})

// 解释为 function (x) { return x }(a++)
// 即调用匿名函数,结果f等于0
var a = 0;
var f = function (x) { return x }
(a++)

只有下一行的开始与本行的结尾,无法放在一起解释,JavaScript 引擎才会自动添加分号。

if (a < 0) a = 0
console.log(a)

// 等同于下面的代码,
// 因为 0console 没有意义
if (a < 0) a = 0;
console.log(a)

另外,如果一行的起首是“自增”(++)或“自减”(--)运算符,则它们的前面会自动添加分号。

a = b = c = 1

a
++
b
--
c

console.log(a, b, c)
// 1 2 0

上面代码之所以会得到1 2 0的结果,原因是自增和自减运算符前,自动加上了分号。上面的代码实际上等同于下面的形式。

a = b = c = 1;
a;
++b;
--c;

如果continuebreakreturnthrow这四个语句后面,直接跟换行符,则会自动添加分号。

return
{ first: 'Jane' };

// 解释成
return;
{ first: 'Jane' };

由于解释引擎自动添加分号的行为难以预测,因此编写代码的时候不应该省略行尾的分号。

不应该省略结尾的分号,还有一个原因。有些 JavaScript 代码压缩器(uglifier)不会自动添加分号,因此遇到没有分号的结尾,就会让代码保持原状,而不是压缩成一行,使得压缩无法得到最优的结果。

另外,不写结尾的分号,可能会导致脚本合并出错。所以,有的代码库在第一行语句开始前,会加上一个分号。

;var a = 1;
// ...

总结:

避免 ASI 带来的问题:

1. 后缀运算符 ++ 或 -- 和它的操作数应该出现在同一行

2. return 或 throw 语句的表达式开始位置应该和 return 或 throw token 同一行

3. break 或 continue 语句的标示符应该和 break 或 continue token 同一行

何时加分号:

在以 ([/+- 开头的语句前加分号(由于正常写法均不会出现以 .,*% 作为语句开头,因此只需记住前面5个即)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值