JavaScript词法结构

本文最后更新于 2025年7月30日 下午

参考:《JavaScript 权威指南(原书第 7 版)》

编程语言的词法结构是一套基本规则,规定了如何使用这门语言编写程序。
词法结构是一门语言最低级的语法,规定了变量如何命名、注释的界定符,以及如何分割程序的语句等等。

JavaScript 程序的文本

JavaScript 区分大小写。这意味着它的关键字、变量、函数名和其他标识符必须始终保持一致的大小写形式。例如,onlineOnlineOnLineONLINE 是 4 个完全不同的变量名。

JavaScript 忽略程序记号之间的空格。很大程度上也忽略换行符。因为可以在程序中随意使用空格和换行符,所以可以按照便于阅读理解的方式对程序进行格式化和缩进。

除了常规空格(\u0020),JavaScript 也将制表符各种 ASCII 控制符Unicode 间格识别为空格。JavaScript 将换行符回车符回车 / 换行序列识别为行终止符。

注释

JavaScript 支持两种注释,单行注释多行注释

  • 单行注释是以 // 开头到一行末尾的内容。
1
// 单行注释
  • 多行注释位于 /**/ 之间,可以跨行,但是不能嵌套。
1
2
3
4
5
6
7
8
9
/* 
多行注释
*/

/* 多行注释 */ // 另一个注释(单行注释)

/*
* 多行注释(美观)
*/

字面量

字面量是一种直接出现在程序中的数据值。如有:

1
2
3
4
5
6
12; // 数值12
1.2; // 数值1.2
("hi"); // 字符串"hi"
("hello world"); // 字符串"hello world"
true; // 布尔值
null; // 空对象

标识符和保留字

简单来说,标识符就是一个名字。在 JavaScript 中,标识符用于在 JavaScript 代码中命名
常量变量属性函数,以及为某些循环提供标记

JavaScript 标识符必须以字母下划线(_)、美元符号($)开头,
后续的字符可以是数字字母下划线美元符号。(数字不能作首个字符,以便区分标识符和数值)

与其他语言一样,JavaScript 为语言自身使用保留了某些标识符。这些“保留字”不能作为常规标识符使用。

Unicode

JavaScript 程序是使用Unicode 字符集编写的,因此在字符串注释中可以使用任意 Unicode 字符。考虑到可移植性和易于编辑,建议在标识符中只使用ASCII 字母数字

但这只是一个编程惯例,语言本身支持在标识符中使用Unicode 字母数字象形文字(但是这不支持表情符号)。这意味着常量或变量的名字中可以包含数字符号或非英语文字。

Unicode 转义序列

Unicode 归一化

可选的分号

JavaScript 使用分号(;)分隔语句,这对于保持代码清晰很重要:如果没有分隔符,一条语句的结尾可能是另一条语句的开头,反之亦然。

在 JavaScript 中,如果两条语句分别写在两行,通常可以省略它们之间的分号。在程序末尾,如果接下来的记号是右花括号(}),那么也可以省略分号。

  • 一种风格是,使用分号明确标识语句结束,即使这些分号并非必需。
  • 另一种风格是,尽可能地省略分号,只在少数必要情况下采用。

无论哪种风格,都需要了解一些关于 JavaScript 中可选分号的细节。

1
2
3
4
5
a = 3; // 第一个分号可以省略
b = 4;

a = 3;
b = 4; // 分号不能省略

JavaScript 并非任何时候都把换行符当作分号,而只是在不隐式添加分号就无法解析代码的情况下才这么做。更准确地讲,只在下一个非空格字符无法被解释为当前语句的一部分时才把换行符当作分号。如:

1
2
3
4
5
6
7
let a;
a = 3;
console.log(a);
// JavaScript将上方代码解释为:
let a;
a = 3;
console.log(a);

但是,这些语句终止规则会导致某些意外情形。如:

1
2
3
4
let y = x + f(a + b).toString();
// 上面代码看起来是两条位于两行的语句,但是第二行的圆括号可以被解释为第一行f的函数调用。
// 所以,JavaScript将上方代码解释为:
let y = x + f(a + b).toString();

而这很有可能不是代码作者的意图。为了保证代码能按代码作者的意图指向,必须在相应的地方添加分号。

通常,如果语句以 ([/+- 开头,就有可能被解释为之前语句的一部分。实践中,以 /+- 开头的语句极少,但以 ([ 开头的语句则并不鲜见。可以在所以这些语句前面都防御性地添加一个分号,这样即使它前面的语句被修改,删掉了之前末尾的分号,也不会影响当前语句。如:

1
2
let x = 0; // 这里省略分号
[x, x + 1, x + 2].forEach(console.log()); // 防御:保证这条语句独立

JavaScript 在不能把第二行解析为第一行的连续部分时,对换行符的解释有三种例外情况。

第一种情况涉及 returnthrowyieldbreakcontinue 语句。这些语句通常独立存在,但是有时候后面也会跟一个标识符或表达式。如果这几个单词后面(任何其他标记前面)有换行符,JavaScript 就会把这个换行符解释为分号。如:

1
2
3
4
5
6
7
8
9
return;
true;

// JavaScript假设你的意图是:
return;
true;

// 但你的意图可能是:
return true;

这意味着,一定不能在 returnbreak 等以上关键字和它们后面的表达式之间添加换行符。那如果加入了换行符,那代码出错后的调试会非常麻烦,因为错误不明显。

第二种情况涉及 ++-- 操作。这些操作符既可以放在表达式前面,也可以放在表达式后面,如果想把这两个操作符作为后置操作符,那它们必须与自己操作的表达式位于同一行。

第三种情况涉及箭头函数,箭头 => 必须跟参数列表在同一行。


JavaScript词法结构
https://xuekeven.github.io/2022/01/25/JavaScript词法结构/
作者
Keven
发布于
2022年1月25日
更新于
2025年7月30日
许可协议