重学前端(13)JavaScript语法:到底要不要写分号呢?

自动插入分号规则
  自动插入分号规则其实独立于所有的语法产生式定义,它的规则说起来非常简单,只有三条。
  • 要有换行符,且下一个符号是不符合语法的,那么就尝试插入分号。
  • 有换行符,且语法中规定此处不能有换行符,那么就自动插入分号。
  • 源代码结束处,不能形成完整的脚本或者模块结构,那么就自动插入分号。
  这样描述是比较难以理解的,我们一起看一些实际的例子进行分析:
let a = 1
void function(a){
    console.log(a);
}(a);
  在这个例子中,第一行的结尾处有换行符,接下来 void 关键字接在 1 之后是不合法的,这命中了我们的第一条规则,因此会在 void 前插入换行符。
var a = 1, b = 1, c = 1;
a
++
b
++c
  这也是个著名的例子,我们看第二行的 a 之后,有换行符,后面遇到了 ++ 运算符,a 后面跟 ++ 是合法的语法,但是我们看看 JavaScript 标准定义中,有 [noLineTerminator here] 这个字样,这是一个语法定义中的规则,你可以感受一下这个规则的内容(下一小节,我会给你详细介绍 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]
  于是,这里 a 的后面就要插入一个 fenhao 了。所以这段代码最终的结果,b 和 c 都变成了 2,而 a 还是 1。
(function(a){
console.log(a);
})()
(function(a){
console.log(a);})()
  这个例子是比较有实际价值的例子,这里两个 function 调用的写法被称作 IIFE(立即执行的函数表达式),是个常见技巧。
  这段代码意图上显然是形成两个 IIFE。
  我们来看第三行结束的位置,JavaScript 引擎会认为函数返回的可能是个函数,那么,在后面再跟括号形成函数调用就是合理的,因此这里不会自动插入分号。
  这是一些鼓励不写分号的编码风格会要求大家写 IIFE 时必须在行首加分号的原因。
function f(){
    return/*
    This is a return value.
    */1;
}
f();
  在这个例子中,return 和 1 被用注释分隔开了。
  根据 JavaScript 自动插入分号规则,带换行符的注释也被认为是有换行符,而恰好的是,return 也有 [no LineTerminator here] 规则的要求。所以这里会自动插入分号,f 执行的返回值是 undefined。
 
 no LineTerminator here 规则
  好了,到这里我们已经讲清楚了分号自动插入的规则,但是我们要想彻底掌握分号的奥秘,就必须要对 JavaScript 的语法定义做一些数据挖掘工作。
  no LineTerminator here 规则表示它所在的结构中的这一位置不能插入换行符。自动插入分号规则的第二条:有换行符,且语法中规定此处不能有换行符,那么就自动插入分号。跟 no LineTerminator here 规则强相关,那么我们就找出JavaScript 语法定义中的这些规则。

 

 

  为了方便你理解,我把产生式换成了实际的代码。
  下面一段代码展示了,带标签的 continue 语句,不能在 continue 后插入换行。
outer:for(var j = 0; j < 10; j++)
for(var i = 0; i < j; i++)
continue /*no LineTerminator here*/ outter
  break 跟 continue 是一样的,break 后也不能插入换行:
outer:for(var j = 0; j < 10; j++)
for(var i = 0; i < j; i++)
break /*no LineTerminator here*/ outter

 

我们前面已经提到过 return 和后自增、后自减运算符。
function f(){
    return /*no LineTerminator here*/1;
}

 

posted @ 2022-04-18 23:45  夏目友人喵  阅读(192)  评论(0编辑  收藏  举报