前端JavaScript基础训练系列一百二十九:自动分号

再看看本章前面那个更为复杂的赋值表达式的例子:

var a = 42;
     var b = "foo";
     var c = false;
     var d = a && b || c ? c || b ? a : c && b : a;
     d;      // 42

掌握了优先级和关联等相关知识之后,就能够根据组合规则将上面的代码分解如下:

    ((a && b) || c) ? ((c || b) ? a : (c && b)) : a

也可以通过缩进显式让代码更容易理解:

(
(a && b)
|| c
)
?
(
(c || b)
? a
:
(c && b)
)
:
a

现在来逐一执行。
(1) (a && b) 结果为 “foo”。
(2) “foo” || c 结果为 “foo”。 (3) 第一个 ? 中,“foo” 为真值。 (4) (c || b) 结果为 “foo”。
(5) 第二个 ? 中,“foo” 为真值。 (6) a 的值为 42。
因此,最后结果为 42。

现在你应该对运算符优先级(和关联)有了更深入的了解,多个运算符串联的代码也不在 话下。
但是我们仍然面临着一个重要问题,即是不是理解和遵守了运算符优先级和关联规则就万 事大吉了?在必要时是否应该使用 ( ) 来自行控制运算符的组合和执行顺序?

换句话说,尽管这些规则是可以学习和掌握的,但其中也不乏问题和陷阱。如果完全依赖 它们来编码,就很容易掉进陷阱。那么是否应该经常使用( )来自行控制运算符的执行而 不再依赖系统的自动操作呢?
正如第 4 章中的隐式强制类型转换,这个问题仁者见仁,智者见智。对于两者,大多数人 的看法都是:要么完全依赖规则编码,要么完全使用显式和自行控制的方式。
对于这个问题,我并没有一个明确的答案。它们各自的优缺点本书都已予以介绍,希望能 有助于你加深理解,从而做出自己的判断。
我认为,针对该问题有个折中之策,即在编写程序时要将两者结合起来,既要依赖运算符 优先级/关联规则,也要适当使用( )自行控制方式。对第4章中的隐式强制类型转换也 是如此,我们应该安全合理地运用它们,而非无节制地滥用。
例如,如果if (a && b && c) …没问题,我就不会使用if ((a && b) && c) …,因为这 样过于繁琐。
然而,如果需要串联两个? :运算符的话,我就会使用( )来自行控制运算符的组合,让 代码更清晰易读。
所以我的建议和第 4 章中一样:如果运算符优先级 / 关联规则能够令代码更为简洁,就使 用运算符优先级 / 关联规则;而如果 ( ) 有助于提高代码可读性,就使用 ( )。

自动分号

有时 JavaScript 会自动为代码行补上缺失的分号,即自动分号插入(Automatic Semicolon
Insertion,ASI)。
因为如果缺失了必要的 ;,代码将无法运行,语言的容错性也会降低。ASI 能让我们忽略
那些不必要的 ;。
请注意,ASI 只在换行符处起作用,而不会在代码行的中间插入分号。
如果 JavaScript 解析器发现代码行可能因为缺失分号而导致错误,那么它就会自动补上分 号。并且,只有在代码行末尾与换行符之间除了空格和注释之外没有别的内容时,它才会 这样做。
例如:

var a = 42, b c;

如果 b 和 c 之间出现 , 的话(即使另起一行),c 会被作为 var 语句的一部分来处理。在 语法 | 111

上例中,JavaScript 判断 b 之后应该有 ;,所以 c; 被处理为一个独立的表达式语句。 又比如:

    var a = 42, b = "foo";
a
b // "foo"

上述代码同样合法,不会产生错误,因为 ASI 也适用于表达式语句。 ASI 在某些情况下很有用,比如:

var a = 42;
do {
// ..
} while (a) // <-- 这里应该有; a;

语法规定 do…while 循环后面必须带 ;,而 while 和 for 循环后则不需要。大多数开发人员 都不记得这一点,此时 ASI 就会自动补上分号。
本章前面讲过,语句代码块结尾不用带 ;,所以不需要用到 ASI: var a = 42;

    while (a) {
         // ..
} // <-- 这里可以没有; a;

其他涉及 ASI 的情况是 break、continue、return 和 yield(ES6)等关键字:

    function foo(a) {
         if (!a) return
a *= 2;
// .. }

由于ASI会在return后面自动加上;,所以这里return语句并不包括第二行的a *= 2。 return 语句的跨度可以是多行,但是其后必须有换行符以外的代码:

    function foo(a) {
         return (
a * 2 + 3 / 12 );
}

上述规则对 break、continue 和 yield 也同样适用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值