JavaScript的词法文法
Icon could not be loaded
9 min read
#notes#JavaScript#Programming

TOC

空白符

空白符提升了源码的可读性,并将标记 (tokens) 区分开。这些符号通常不影响源码的功能。通常可以用压缩器来移除源码中的空白,减少数据传输量。

代码点名称缩写说明转义序列
U+0009制表符<HT>水平制表符\t
U+000B垂直制表符<VT>垂直制表符\v
U+000C分页符<FF>分页符(Wikipedia\f
U+0020空格<SP>空格
U+00A0无间断空格<NBSP>在该空格处不会换行
Others其他 Unicode 空白<USP>Wikipedia 上对 Unicode 空白的介绍

行终止符

除了空白符之外,行终止符也可以提高源码的可读性。不同的是,行终止符可以影响 JavaScript 代码的执行。行终止符也会影响自动分号补全的执行。在正则表达式中,行终止符会被 \s 匹配。

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

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

注释

注释用来在源码中增加提示、笔记、建议、警告等信息,可以帮助阅读和理解源码。在调试时,可以用来将一段代码屏蔽掉,防止其运行;这也是一个有价值的调试工具。

在 JavaScript 中,有两种常见的添加注释的方法:行注释和块注释。另外,也有一种特殊的 hashbang 注释语法。

行注释

// 风格的注释,会将该行中符号以后的文本都视为注释:

function comment() {
  // 这是单行注释
  console.log("Hello world!");
}
comment();

块注释

是 /* */ 风格的注释,这种方式更加灵活,可以在单行内使用多行注释,也可以用来实现多行注释,也可以用于行内注释:

function comment(x) {
  /* 这是单行注释 */
  
  /* 
    这是多行注释, 
    注意在写完注释前无需终止注释 
  */
  
  console.log("Hello " + x /* 引入 x 的值 */ + " !");
}
comment("world");

Hashbang注释

Hashbang 注释是一种特殊的注释语法,其行为与单行注释(//)完全一样,只是它以 #! 开头,并且只在脚本或模块的最开始处有效。注意,#! 标志之前不能有任何空白字符。注释由 #! 之后的所有字符组成直到第一行的末尾;只允许有一条这样的注释。JavaScript 中的 hashbang 注释类似于 Unix 中的 shebang,它提供了一个特定的 JavaScript 解释器的路径,你想用它来执行这个脚本。在 hashbang 注释标准化之前,它已经在非浏览器主机(如 Node.js)中得到了事实上的实现,在那里,它在被传递给引擎之前被从源文本中剥离。示例如下:

#!/usr/bin/env node
console.log("Hello world");

下面是zxJavaScript解释器的示例:

#!/usr/bin/env zx
await $`cat package.json | grep name`

关键字

ECMAScript 6 中的保留关键字

未来保留关键字

在 ECMAScript 规格中,这些关键字被当成关键字保留。目前它们没有特殊功能,但是在未来某个时间可能会加上。所以这些关键字不能当成标识符使用。这些关键字在严格模式和非严格模式中均不能使用。

以下关键字只在严格模式中被当成保留关键字:

以下关键字只在模块代码中被当成保留关键字:

之前标准中的保留关键字

这里是之前版本中的 ECMAScript(1 到 3)中的保留关键字:

另外,字面量 nulltruefalse同样不能被当成标识使用。 保留字是仅针对标识符(Identifier)的文法定义而言的(而不是标识符名(IdentifierName)的文法定义)。

// 标识符用于函数声明式和函数表达式。
function import() {} // Illegal.

字面量

空字面量

null

布尔字面量

true
false

数值字面量

// 十进制
 
1234567890
42
// 谨慎使用 0 开头的数值:
0888 // 转换为十进制 888
0777 // 转换为八进制 777,十进制 511
 
// 二进制
var FLT_SIGNBIT  = 0b10000000000000000000000000000000; // 2147483648
var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607
 
// 八进制
var n = 0O755; // 493
var m = 0o644; // 420
 
// 十六进制
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
0x123456789ABCDEF   // 81985529216486900
0XA                 // 10

对象字面量

var o = { a: "foo", b: "bar", c: 42 };
 
// ES6 中的简略表示方法
var a = "foo", b = "bar", c = 42;
var o = {a, b, c};
// 不需要这样
var o = { a: a, b: b, c: c };

数组字面量

[1954, 1974, 1990, 2014]

字符串字面量

'foo'
'bar'

十六进制转义序列

"\xA9" // "©"

Unicode转义序列

"\u00A9" // "©"

Unicode编码转义

"\u{2F804}";
 
// 使用单纯 Unicode 转义
"\uD87E\uDC04";

正则表达式字面量

/ab+c/g

模板字面量

`string text`
 
`string text line 1
 string text line 2`
 
`string text ${expression} string text`
 
tag`string text ${expression} string text`

自动分号补全

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

ECMAScript 规格提到自动分号补全的三个规则

  1. 当出现一个不允许的行终止符或“}”时,会在其之前插入一个分号。
  2. 当捕获到标识符输入流的结尾,并且无法将单个输入流转换为一个完整的程序时,将在结尾插入一个分号。
  3. 当语句中包含语法限制后跟一个行终止符的时候,将会在结尾插入一个分号。