JS 词法文法

102 阅读3分钟

什么是JS的词法文法?

程序语言是需要编译的,即把源文件翻译成与平台无关的目标代码

编译一般由三个步骤构成:

  1. 词法分析:输入源文件,输出token流
  2. 文法分析:输入token流,输出抽象语法树
  3. 语义分析:输入抽象语法树,输出目标代码

源文件是一种字符流,它会被从左到右扫描,并被转换为一系列的输入元素,包括 token、控制符、空白符、行终止符和注释。

token又叫词法符号,是一种编译器内部结构,它们不能被分解为更小的单位

编译器会根据token词、控制符、空白符、行终止符和注释这些基本单元生成抽象语法树。

除此之外,JS中定义了自动分号补全规则。

以上构成了JS的词法文法这块的知识。

下面,我们来分别看看这些词法元素和自动分号补全规则在JS中的含义。

token

token是指代码中的基本语法单元,JS中对标识符、关键字、字面量这些token做了一些规定(还有运算符、分隔符等token这里不做介绍,放到数据的运算那块再谈)。

标识符

由Unicode 字母、数字、下划线和美元符号组成,第一个字母不能是数字。

关键字

JS中有些保留关键字,不能被当作标识符使用。这些关键字会被用在各种地方,有些用于声明数据,有些是运算符,有些用于流程控制,有些用在函数体内,有些用在对象定义中......

break、case、catch、class、const、continue、debugger、default、delete、do、else、export、extends、finally、for、function、if、import、in、instanceof、new、return、super、switch、this、throw、try、typeof、var、void、while、with、yield、enum、implements、interface、let、package、private、protected、public、static、await

字面量

  • 空字面量:null
  • 布尔字面量:true、false
  • 数值字面量:二进制、八进制、十进制、十六进制、数值分隔符
  • 字符串字面量:''
  • 模板字面量:``
  • 正则表达式字面量:/ab+c/g
  • 数组字面量:[]
  • 对象字面量:{}

格式控制符

格式控制符又叫零宽字符,用于控制对源码文本的解释,但是并不会显示出来。

请看下面这段代码,不知道大家有没有遇到过这样的bug,明明两个相同的字符串,比较的结果却是false,原因就是字符串里包含零宽字符,只是它们被隐藏了,我们看不到。

零宽字符.png

空白符

空白符提升了源码的可读性,并将标记 (tokens) 区分开。

编码名称说明转义序列
U+0009制表符水平制表符\t
U+000B垂直制表符垂直制表符\v
U+000C分页符分页符\v
U+0020空格空格
U+00A0无间断空格在该空格处不会换行
Others其他 Unicode 空白

行终止符

除了空白符之外,行终止符也可以提高源码的可读性。不同的是,行终止符可以影响JS代码的执行,行终止符也会影响自动分号补全的执行。

只有下列 Unicode 字符会被当成行终止符,其他的行终止符(比如 Next Line、NEL、U+0085 等)都会被当成空白符。

编码名称说明转义序列
U+000A换行符在 UNIX 系统中起新行\n
U+000D回车符在 Commodore 和早期的 Mac 系统中起新行\n
U+2028行分隔符
U+2029段分隔符

注释

  • 行注释://
  • 块注释:/**/
  • Hashbang 注释:#!

自动分号补全

一些JS语句必须用分号结束,所以会被自动分号补全 (ASI) 影响,比如:

  • 空语句
  • let、const、变量声明
  • import、export、模块定义
  • 表达式语句
  • debugger
  • continue、break、throw
  • return