什么是JS的词法文法?
程序语言是需要编译的,即把源文件翻译成与平台无关的目标代码。
编译一般由三个步骤构成:
- 词法分析:输入源文件,输出token流
- 文法分析:输入token流,输出抽象语法树
- 语义分析:输入抽象语法树,输出目标代码
源文件是一种字符流,它会被从左到右扫描,并被转换为一系列的输入元素,包括 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,原因就是字符串里包含零宽字符,只是它们被隐藏了,我们看不到。
空白符
空白符提升了源码的可读性,并将标记 (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