词法文法 - JavaScript 编辑
这部分描述了JavaScript 的词法(lexical grammar)。ECMAScript 源码文本会被从左到右扫描,并被转换为一系列的输入元素,包括 token、控制符、行终止符、注释和空白符。ECMAScript 定义了一些关键字、字面量以及行尾分号补全的规则。
格式控制符
格式控制符用于控制对源码文本的解释,但是并不会显示出来。
代码点 | 名称 | 缩写 | 说明 |
---|---|---|---|
U+200C | 零宽度非结合子 | <ZWNJ> | 放置在一些经常会被当成连字的字符之间,用于将它们分别以独立形式显示(Wikipedia) |
U+200D | 零宽度结合子 | <ZWJ> | 放置在一些通常不会被标记为连字的字符之间,用于将这些字符以连字形式显示(Wikipedia) |
U+FEFF | 字节流方向标识 | <BOM> | 在脚本开头使用,除了将脚本标记为Unicode格式以外,还用来标记文本的字节流方向(Wikipedia) |
空白符
空白符提升了源码的可读性,并将标记 (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 中,有两种添加注释的方法。
第一种是单行注释(single-line comment),使用 //
,会将该行中符号以后的文本都视为注释:
function comment() {
// 这是单行注释
console.log("Hello world!");
}
comment();
第二种是多行注释(multiple-line comment),使用 /* */
,这种方式更加灵活:
比如,可以在单行内使用多行注释:
function comment() {
/* 单行注释 */
console.log("Hello world!");
}
comment();
也可以用来实现多行注释:
function comment() {
/* 多行注释,
直到终止符号才结束 */
console.log("Hello world!");
}
comment();
多行注释也可以用于行内注释,但这样会使代码可读性变差,所以要谨慎使用:
function comment(x) {
console.log("Hello " + x /* 引入x的值 */ + " !");
}
comment("world");
另外,块注释也可以用来屏蔽一段代码,只要将这段代码用块注释包裹起来就可以了:
function comment() {
/* console.log("Hello world!"); */
}
comment();
注释中的 console.log()
的调用始终无效。这种方式可以屏蔽任意多行的代码,也可以屏蔽一行代码的一部分。
Hashbang 注释
专门的第三个注释语法,hashbang 注释正在 ECMAScript 中标准化(参见 Hashbang 语法建议)。
Hashbang 注释的行为与单行(//
)注释完全相同,但它以 #!
开头且仅在脚本或模块的绝对开头有效。还要注意,在 #!
之前不允许有任何类型的空格。注释由 #!
之后的所有字符组成直到第一行的末尾;只允许有一条这样的注释。
Hashbang 注释指定特定 JavaScript 解释器的路径要用于执行脚本。示例如下:
#!/usr/bin/env node
console.log("Hello world");
注意:JavaScript 中的 hashbang 注释模仿 Unix 中的 shebangs,用于指定适当的解释器运行文件。
尽管在 hashbang 注释之前的 BOM 在浏览器中能工作,但不建议在具有 hashbang 的脚本中使用 BOM。当您尝试在 Unix/Linux 中运行脚本时,有 BOM 将不工作。因此,如果要直接从 shell 运行脚本,请使用没有 BOM 的 UTF-8。
您只能使用 #!
注释样式以指定 JavaScript 解释器。在所有其他情况下,只需使用 //
注释(或多行注释)。
关键字
ECMAScript 6 中的保留关键字
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
未来保留关键字
在 ECMAScript 规格中,这些关键字被当成关键字保留。目前它们没有特殊功能,但是在未来某个时间可能会加上。所以这些关键字不能当成标识符使用。这些关键字在严格模式和非严格模式中均不能使用。
enum
以下关键字只在严格模式中被当成保留关键字:
implements
interface
let
package
private
protected
public
static
以下关键字只在模块代码中被当成保留关键字:
await
之前标准中的保留关键字
这里是之前版本中的ECMAScript(1到3)中的保留关键字:
abstract
boolean
byte
char
double
final
float
goto
int
long
native
short
synchronized
transient
volatile
另外,直接量null
、true
和false
同样不能被当成标识使用。
保留字的使用
事实上保留字是仅针对标识符(Identifier)的文法定义而言的(而不是标识符名(IdentifierName)的文法定义)。如 es5.github.com/#A.1中所描述的, 这些都是不排斥保留字的标识符名.
a.import
a["import"]
a = { import: "test" }.
另一方面,如下用法是不允许的。因为它是一个标识符,而标识符的文法定义是除保留字以外的标识符名。标识符用于函数声明式和函数表达式.
function import() {} // Illegal.
直接量
空直接量
更多信息可以参考null
null
布尔直接量
更多信息可以参考Boolean
true
false
数值直接量
十进制
1234567890
42
// 谨慎使用 0 开头的数值:
0888 // 转换为十进制 888
0777 // 转换为八进制 777,十进制 511
请注意,十进制数值直接量可以以 0 开头,但是如果 0 以后的最高位比 8 小,数值将会被认为是八进制而不会报错。更多信息可以参考 bug 957513 和 parseInt()
。
二进制
二进制表示为开头是0后接大写或小写的B(0b
或者0B
)。这是ECMAScript 6中的新语法,可以参考下面的浏览器兼容性表格。如果0b
之后有除了0或1以外的数字,将会抛出SyntaxError
:“Missing binary digits after 0b”。
var FLT_SIGNBIT = 0b10000000000000000000000000000000; // 2147483648
var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607
八进制
八进制表示为开头是0后接大写或小写的O(0o
或0O
)。这是ECMAScript 6中的新语法,可以参考下面的浏览器兼容性表格。如果有不在(01234567)中的数字,将会抛出SyntaxError
:“Missing octal digits after 0o”。
var n = 0O755; // 493
var m = 0o644; // 420
// 用0开头也可以实现(请查看上方十进制有关部分)
0755
0644
十六进制
十六进制表示为开头是0后接大写或小写的X(0x
或0X
)。如果有不在(0123456789ABCDEF)中的数字,将会抛出SyntaxError
:“Identifier starts immediately after numeric literal”。
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 };
数组直接量
更多信息可以参考 Array
。
[1954, 1974, 1990, 2014]
字符串直接量
'foo'
"bar"
十六进制转义序列
'\xA9' // "©"
Unicode 转义序列
Unicode 转义序列要求在\u
之后至少有四个字符。
'\u00A9' // "©"
Unicode 编码转义
ECMAScript 6新增特性。使用Unicode编码转义,任何字符都可以被转义为十六进制编码。最高可以用到0x10FFFF
。使用单纯的Unicode转义通常需要写成分开的两半以达到相同的效果。
可以参考String.fromCodePoint()
和String.prototype.codePointAt()
。
'\u{2F804}'
// 使用单纯 Unicode 转义
'\uD87E\uDC04'
正则表达式直接量
更多信息可以参考 RegExp
。
/ab+c/g
// 一个空的正则表达式直接量
// 必须有一个空的非捕获分组
// 以避免被当成是行注释符号
/(?:)/
模板直接量
更多信息可以参考template strings。
`string text`
`string text line 1
string text line 2`
`string text ${expression} string text`
tag `string text ${expression} string text`
自动分号补全
一些 JavaScript 语句必须用分号结束,所以会被自动分号补全 (ASI)影响:
- 空语句
let
、const
、变量声明import
、export
、模块定义- 表达式语句
debugger
continue
、break
、throw
return
ECMAScript 规格提到自动分号补全的三个规则。
1. 当出现一个不允许的行终止符或“}”时,会在其之前插入一个分号。
{ 1 2 } 3
// 将会被 ASI 转换为
{ 1 2 ;} 3;
2. 当捕获到标识符输入流的结尾,并且无法将单个输入流转换为一个完整的程序时,将在结尾插入一个分号。
在下面这段中,由于在 b
和 ++
之间出现了一个行终止符,所以 ++
未被当成变量 b
的后置运算符。
a = b
++c
// 将被 ASI 转换为
a = b;
++c;
3. 当语句中包含语法中的限制产品后跟一个行终止符的时候,将会在结尾插入一个分号。带“这里没有行终止符”规则的语句有:
- 后置运算符(
++
和--
) continue
break
return
yield
、yield*
module
return
a + b
// 将被 ASI 转换为
return;
a + b;
规格
规格 | 状态 | 备注 |
---|---|---|
ECMAScript 1st Edition (ECMA-262) | Standard | 初始定义 |
ECMAScript 5.1 (ECMA-262) Lexical Conventions | Standard | |
ECMAScript 2015 (6th Edition, ECMA-262) Lexical Grammar | Standard | 增加:二进制和八进制数值直接量,Unicode 编码转义直接量、模板直接量 |
浏览器兼容性
BCD tables only load in the browser
The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.参见
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论