编程语言的词法结构是一套基本规则,规定了如何使用这门语言编写程序,规定了变量如何命名、注释的定界符、如何分隔程序的语句等
ECMAScript 源码文本会被从左到右扫描,并被转换为一系列的输入元素(Token),包括标识符、控制符、行终止符、注释和空白符
JavaScript 代码的文本
字符集
JavaScript 代码使用 Unicode 字符集
区分大小写
- JavaScript 是区分大小写的语言
- 而 HTML 和 CSS 并不区分大小写(尽管 XML 区分大小写)
- 也就是说如果用 JavaScript 控制 HTML 属性时,对 HTML 来说
id
和ID
没区别,但 JavaScript 有区别
空白字符
JavaScript 会忽略程序中标识(Token)之间的空格,多数情况下同样会忽略换行符。因此可以采用整齐、一致的缩进、空格等来形成统一的格式,从而提高代码的可读性
可打印字符在渲染时会产生输出,但空白字符不会。空白字符在有限程度上定义了文本的布局,如:
- 空白
- 换行
- 中断彼此相邻的渲染字符的正常顺序
- …
常见的识别为空格的空白字符
名称 | Unicode 转义序列 | 转义符 | HTML/XML命名实体 | 说明 |
---|---|---|---|---|
水平制表符 | \u0009 | \t | 	 | <HT> |
空格符 | \u0020 | 普通空格 | ||
非中断空格符 | \u00A0 | 、  | 与空格相同,但不是可以断行的点 | |
零宽空格 | \u200B | ​ | <ZWSP> ,不使用显式空格向文本处理系统指示单词边界 | |
零宽非连接符 | \u200C | ‌ | <ZWNJ> ,中断彼此相邻的字符关联 | |
零宽连接器 | \u200D | ‍ | <ZWJ> ,使左右字符关联 | |
非中断零宽空格 | \u2060 | ⁠ | <WJ> ,与零宽空格相同,但不是可以断行的点 |
常见的行终止符
名称 | Unicode 转义序列 | 转义符 | HTML/XML 命名实体 | 说明 |
---|---|---|---|---|
换行符 | \u000A | \n | 
 | <LF> |
垂直制表符 | \u000B | \v | <VT> | |
进纸符 | \u000C | \f | <FF> | |
回车符 | \u000D | \r | <CR> | |
下一行 | \u0085 | <NEL> | ||
行分隔符 | \u2028 | <LS> | ||
段落分割符 | \u2029 | <PS> |
注释
注释不会被执行,是给阅读代码的人看的
可以添加注释来对代码进行解释、提高代码的可读性,或者将代码注释,以阻止其执行
单行注释
// 注释内容
// 可以独占一行
const a = 6 // 也可以放到代码行末
多行注释
/* 注释内容
注释内容
注释内容 */
const a = /* 可以在代码中间 */ 6
为了美观,常写成:
/**
* 注释内容
* 注释内容
* 注释内容
*/
块级注释左部分 /*
会匹配第一个 */
,所以下面案例都是会报错的:
// 1: 块级注释嵌套
/*
注释 1
/* 注释 1.1 */
*/
// 2: 正则表达式字面量
/*
var rm_a = /a*/.match(s);
*/
字面量
字面量,又名直接量(Literals)
// 空字面量
null
// 布尔字面量
true
false
// 数值字面量
123_000
0b10101
0o63
0x4f
1.6e5
// 字符串字面量
'foo'
"bar"
`foo-bar`
// 对象字面量
{ a: 'foo', b: 'bar', c: 42 }
// 数组字面量
[1954, 1974, 1990, 2014]
// 正则表达式字面量
/ab+c/g
/(?:)/
标识符
标识符:给变量、函数、函数形参、属性(对象的键)命名的字符序列
命名规则(必须遵守的硬性规定):
- 由 26 个英文字母大小写、0-9、
_
或$
组成 - 数字不可以开头
- 不可以使用关键字和保留字,但能包含关键字和保留字
- 严格区分大小写,长度无限制
- 标识符不能包含空格
其实标识符中的字母也可以包含扩展的 ASCII 或 Unicode 字母字符,但不推荐
命名规范(建议遵守的软性要求):
- 类名、构造函数名、组件名(Vue、React):大驼峰命名法,
XxxYyyZzz
- 变量名、函数名、形参名、属性名:小驼峰命名法,
xxxYyyZzz
- 常量名:所有字母都大写,多单词时每个单词用下划线连接,
XXX_YYY_ZZZ
- 这里的常量不是指
const
修饰,而是业务逻辑意义上的不变值,如:加载因子、配置数量
- 这里的常量不是指
- 文件名:
- 组件(Vue、React):大驼峰命名法,
XxxYyyZzz.js
- 其他正常文件:最常见的是第一种,当然也有人使用第二三种
- 小驼峰命名法:
xxxYyyZzz.js
- 中划线法:
xxx-yyy-zzz.js
- 下划线法:
xxx_yyy_zzz.js
- 小驼峰命名法:
- 组件(Vue、React):大驼峰命名法,
关键字和保留字
JavaScript 保留关键字
JavaScript 保留了一些标识符为自己所用(已经用到或以后扩展使用)
abstract | arguments | boolean | break | byte |
case | catch | char | class | const |
continue | debugger | default | delete | do |
double | else | enum | eval | export |
extends | false | final | finally | float |
for | function | goto | if | implements |
import | in | instanceof | int | interface |
let | long | native | new | null |
package | private | protected | public | return |
short | static | super | switch | synchronized |
this | throw | throws | transient | true |
try | typeof | var | void | volatile |
while | with | yield |
JavaScript 对象、属性和方法
JavaScript 内置的对象、属性和方法名
Array | Date | eval | function | hasOwnProperty |
Infinity | isFinite | isNaN | isPrototypeOf | length |
Math | NaN | name | Number | Object |
prototype | String | toString | undefined | valueOf |
Java 保留关键字
JavaScript 经常与 Java 一起使用
getClass | java | JavaArray | javaClass | JavaObject | JavaPackage |
window 保留关键字
浏览器运行时
alert | all | anchor | anchors | area |
assign | blur | button | checkbox | clearInterval |
clearTimeout | clientInformation | close | closed | confirm |
constructor | crypto | decodeURI | decodeURIComponent | defaultStatus |
document | element | elements | embed | embeds |
encodeURI | encodeURIComponent | escape | event | fileUpload |
focus | form | forms | frame | innerHeight |
innerWidth | layer | layers | link | location |
mimeTypes | navigate | navigator | frames | frameRate |
hidden | history | image | images | offscreenBuffering |
open | opener | option | outerHeight | outerWidth |
packages | pageXOffset | pageYOffset | parent | parseFloat |
parseInt | password | pkcs11 | plugin | prompt |
propertyIsEnum | radio | reset | screenX | screenY |
scroll | secure | select | self | setInterval |
setTimeout | status | submit | taint | text |
textarea | top | unescape | untaint | window |
HTML 事件句柄
onblur | onclick | onerror | onfocus |
onkeydown | onkeypress | onkeyup | onmouseover |
onload | onmouseup | onmousedown | onsubmit |
Unicode
ECMAScript 要求支持 Unicode 字符集,Unicode 是 ASCII 和 Latin-1 的超集,支持地球上几乎所有在使用的语言
- 因此在字符串和注释中可以使用任意 Unicode 字符
- 但是考虑到可移植性和易于编辑,建议在标识符中只使用 ASCII 字母和数字
Unicode 转义序列
在有些计算机硬件和软件中,无法显示或输入 Unicode 字符全集,JavaScript 定义了一种特殊序列来代表任意 16 位 Unicode 内码。格式为 \u
其后跟随 4 个十六进制数,可以用于 JavaScript 字面量、正则表达式和标识符中(关键字除外)
const café = 1 // 使用 Unicode 字符定义一个变量
caf\u00e9 // => 1;使用转义序列访问这个变量
caf\u{e9} // => 1;相同转义序列的另一种形式
JavaScript 早期版本只支持 4 位数字转义序列;带花括号的版本是 ES6 新增的,目的是更好地支持大于 16 位的 Unicode 码点,比如表情符号:
console.log('\u{1F600}') // 😀
Unicode 归一化
如果在程序中使用了非 ASCII 字符,那必须知道 Unicode 允许用多种编码方式表示同一个字符
如,字符串 'é'
:
- 可以被编码为一个 Unicode 字符
\u00E9
- 也可以被编码为一个常规 ASCII 字符
e
后跟一个重音组合标记\u0301
这两种编码在文本编辑器中看起来完全相同,但它们的二进制编码不同,因此 JavaScript 认为它们不同,而这可能导致非常麻烦的问题:
const café = 1; // 'caf\u{e9}'
const café = 2; // 'cafe\u{301}'
café // => 1
café // => 2
- Unicode 标准为所有字符定义了首选编码并规定了归一化例程,用于把文本转换为适合比较的规范形式
- JavaScript 假定自己解释的源代码已经归一化,它自己不会执行任何归一化
- 如果想在 JavaScript 程序中使用 Unicode 字符,应该保证使用自己的编辑器或其他工具对自己的源代码执行 Unicode 归一化,以防其中包含看起来一样但实际不同的标识符
分号
JavaScript 使用分号 ;
将语句分隔开,但并不严格要求分号
当有地方需要分号时,它会在背后悄悄地添加分号,这被称为自动分号插入(Automatic Semicolon Insertion)
自动分号插入(ASI)规则
在解析源代码的过程中,当发现这些特殊情况时,JavaScript 解析器会自动添加一个分号:
- 下一行是别的代码开始,打断了当前的代码
- 出现
}
时,会在其之前插入一个分号 - 到达源代码文件的结尾
- 当前行有
return
语句 - 当前行有
break
语句 - 当前行有
continue
语句 - 当前行有
throw
语句 - 当前行有
yield
、yield*
语句
省略分号的注意点
一个新行如果以下面符号开头,需要在最前面手动加上分号:
(
:小括号[
:方括号/
:正则表达式开头的斜杠+
:加号-
:减号
实际代码中,这几种情况颇为少见