Javascript分号规则的知识介绍(附示例)
花点时间搞分明JS中的分号规则吧~~~不管你喜爱结尾带分号或省略分号的模式
分号同意的场景
分号一样同意显现在大部分语句(statement)的末尾,比方 do-while statement , var statements, expression statements , continue , return , break statement, throw, debugger 等
栗子:
do Statement while ( Expression ) ; 4+4; f(); debugger;
仅有一个分号 ; 可以表示空语句——在JS中合法,比方 ;;;
可解析为三个空语句(empty statement)
空语句可用于辅助发生语法合法的解析结果,如:
while(1);
假如没有末尾的分号,将会发生解析错误 —— 前提轮回后必需跟从一个语句
分号还会显现在 for 轮回 for ( Expression ; Expression ; Expression ) Statement 中
最后,分号还会显现在 字符串 或 正则表达式中 —— 表示分号本身
分号可以省略的场景
有些场景下分号可以省略,解析器在解析语句时会按照需要主动插入分号,大约流程可以这样懂得:
书写省略 => 解析器解析时发明缺少时会没法准确解析 => 主动增加分号
so 需要明白能主动插入分号的场景,并明白不会主动插入分号且会引发解析错误的状况
规则1:当下一个 token (offending token) 和当前解析的 token (previous token) 没法组成合法语句,且知足以下一个或多个前提时,将会在 offending token 前插入一个分号:
- offending token 和 previous token 被至少一个换行符分割(LineTerminator),且分号插入的作用不是被解析为 空语句 (empty statement)
- offending token 是 }
- previous token 是 ), 并且插入的分号将被解析为do-while语句的终止分号
还要思考一种优先级更高的前提:假如插入的分号会被解析为一个空语句,或是 for 语句的头部两个分号之一,这时不会插入分号(除了 do-while 语句的终止分号外)
规则2:当解析抵达源代码文件 (input stream) 的末尾时,将主动增加一个分号标识解析完毕
规则3:相符 restricted production 语法的语句 —— 比力难翻译,看不懂的可以直接看栗子,这种状况主要描写的是:不该该显现换行符的地方显现换行符致使插入分号引发原语句含义转变
同时知足以下前提,将在 offending token 前主动插入一个分号:
- offending token 和 previous token 组成合语法的 restricted production 语句
- offending token 显现于 restricted production 语句描写中的 [no LineTerminaator here] 部分 ( the token would be the first token for a terminal or nonterminal immediately following the annotation “[no LineTerminator here]” within the restricted production )
- offending token 和 previous token 之间至少存在一个换行符 (LineTerminator)
其中 restricted production 包罗且只要以下:
UpdateExpression[Yield, Await]: LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ContinueStatement[Yield, Await]: continue; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await]; BreakStatement[Yield, Await]: break; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await]; ReturnStatement[Yield, Await]: return; return [no LineTerminator here] Expression [+In, ?Yield, ?Await]; ThrowStatement[Yield, Await]: throw [no LineTerminator here] Expression [+In, ?Yield, ?Await]; ArrowFunction[In, Yield, Await]: ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] YieldExpression[In, Await]: yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await]
简便总结:
使用 a++ 语句时,变量和 ++ 必需在统一行,不然会在 ++ 前插入分号致使语义不一样
return throw yield continue break 后假如紧跟着换行,将会主动增加分号
箭头函数的 => 此前不该该有换行符
栗子 & 大概不相符预测的状况
相符预测状况
// 相当于 42;"hello" 42 "hello" // offending token 是 } if(x){y()} // previous token 是 ) 且插入分号是 do while 语句的完毕 var a = 1 do {a++} while(a<100) console.log(a) // 不会解析成 b++ 由于 b和++之间存在换行符,会在 b 之后主动插入分号 a = b ++c
大概不相符预测的状况
const hey = 'hey' const you = 'hey' const heyYou = hey + ' ' + you ['h', 'e', 'y'].forEach((letter) => console.log(letter))
会收到错误 Uncaught TypeError: Cannot read property 'forEach' of undefined , 由于 you 和 ['h', 'e', 'y'] 的连接能命中合法语法,故它们之间不会主动插入分号 —— 与预测不一致,JS尝试将代码解析为:
const hey = 'hey'; const you = 'hey'; const heyYou = hey + ' ' + you['h', 'e', 'y'].forEach((letter) => console.log(letter))
再看一种状况:
const a = 1 const b = 2 const c = a + b (a + b).toString()
会激发 TypeError: b is not a function
报错,由于会被说明为:
const a = 1 const b = 2 const c = a + b(a + b).toString()
除了 do while 语句外,不会有插入分号作为空语句的其他状况,或作为 for 语句头部的两个必要分号 :
if (a > b) else c = d for (a; b )
以上均不是合法的 JS 语句,并且会引发报错
故以下栗子中的每一个分号都不克不及省略!!
// for轮回没有轮回体的状况,每一个分号都不克不及省略 for (node=getNode(); node.parent; node=node.parent) ;
再看一个带具体注释的例子:
var // 这一行不会插入分号 ,由于 下一行的代码不会毁坏当前行的代码 a = 1 // 这一行会插入分号 let b = 2 // 再比方这种状况,你的原意大概是定义 `a` 变量,再施行 `(a + 3).toString()`, // 但是其实 JavaScript 解析器解析成了,`var a = 2(a + 3).toString()`, // 这时会抛出错误 Uncaught TypeError: 2 is not a function var a = 2 (a + 3).toString() // 同理,下面的代码会被说明为 `a = b(function(){...})()` a = b (function(){ ... })()
以上都是未能命中规则1而未插入分号致使解析与预测不相符的状况
看一个基于规则3的例子:
(() => { return { color: 'white' } })()
预测是返回一个包括 color 属性的对象,但事实上 return 后会被插入一个分号,而致使终究返回 undefined,可以通过在 return 后立即放置花括号 { :
(() => { return { color: 'white' } })()
省略分号的最好实践
不要使用以下单个字符 ( [ / + - 开端一行 , 会极有大概和上一行语句合在一起被解析( ++ 和 -- 不相符单个 +、- 字符)
留意 return break throw continue 语句,假如需要跟从参数或表达式,把它增加到和这些语句统一行,针对 return 返回内容较多的状况 (大对象,柯里化调取,多行字符串等),可以参照 规则1,幸免命中该规则而引发非预测的分号插入,比方:
return obj.method('abc') .method('xyz') .method('pqr') return "a long string\n" + "continued across\n" + "several lines" totalArea = rect_a.height * rect_a.width + rect_b.height * rect_b.width + circ.radius * circ.radius * Math.PI后缀运算符 ++ -- 需要和操纵变量在统一行使用
当然大部分工程化状况下,我们终究会配合Eslint使用带分号或省略分号标准~~~
本篇文章到这里就已经全部完毕了,更多其他出色内容可以关注PHP中文网的JavaScript视频教程栏目!
以上就是Javascript分号规则的知识介绍(附示例)的具体内容,更多请关注百分百源码网其它相关文章!