首页 web前端 js教程 Javascript分号规则的知识介绍(附示例)

Javascript分号规则的知识介绍(附示例)

Mar 25, 2019 pm 02:21 PM
javascript 语法

本篇文章给大家带来的内容是关于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 = &#39;hey&#39;
const you = &#39;hey&#39;
const heyYou = hey + &#39; &#39; + you

[&#39;h&#39;, &#39;e&#39;, &#39;y&#39;].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分号规则的知识介绍(附示例)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用WebSocket和JavaScript实现在线语音识别系统 如何使用WebSocket和JavaScript实现在线语音识别系统 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术 WebSocket与JavaScript:实现实时监控系统的关键技术 Dec 17, 2023 pm 05:30 PM

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统 如何利用JavaScript和WebSocket实现实时在线点餐系统 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

JavaScript和WebSocket:打造高效的实时天气预报系统 JavaScript和WebSocket:打造高效的实时天气预报系统 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

简易JavaScript教程:获取HTTP状态码的方法 简易JavaScript教程:获取HTTP状态码的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

lambda 表达式的语法和结构有什么特点? lambda 表达式的语法和结构有什么特点? Apr 25, 2024 pm 01:12 PM

Lambda表达式是无名称的匿名函数,其语法为:(parameter_list)->expression。它们具有匿名性、多样性、柯里化和闭包等特点。实际应用中,Lambda表达式可用于简洁地定义函数,如求和函数sum_lambda=lambdax,y:x+y,并通过map()函数应用于列表来进行求和操作。

如何在JavaScript中获取HTTP状态码的简单方法 如何在JavaScript中获取HTTP状态码的简单方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP状态码获取方法简介:在进行前端开发中,我们常常需要处理与后端接口的交互,而HTTP状态码就是其中非常重要的一部分。了解和获取HTTP状态码有助于我们更好地处理接口返回的数据。本文将介绍使用JavaScript获取HTTP状态码的方法,并提供具体代码示例。一、什么是HTTP状态码HTTP状态码是指当浏览器向服务器发起请求时,服务

如何使用WebSocket和JavaScript实现在线协作编辑器 如何使用WebSocket和JavaScript实现在线协作编辑器 Dec 17, 2023 pm 01:37 PM

实时协作编辑器已经成为现代web开发的标配,特别是在各种团队协作、在线文档编辑和任务管理的场景下,基于WebSocket的实时通信技术可以提高团队成员之间的沟通效率和协作效果。本文将介绍如何使用WebSocket和JavaScript构建一个简单的在线协作编辑器,帮助读者更好地理解WebSocket的原理和使用方法。理解WebSocket的基本原理WebSo

See all articles