/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}
词法与基本语法
本篇内容:词法(Unicode、转义序列、注释、字面量、标识符、关键字与保留字)、语句与声明、ASI、变量声明的语法形式、严格模式。属 ECMA-262 语言层(§11 词法、§12 语句、§9 执行上下文、§16 脚本与模块的语义)。
白话导读:本文讲 JavaScript 代码最底层的写法规则——怎么写字面量、怎么命名、注释怎么写、分号能不能省、严格模式到底管什么。这些是读任何 JS 代码都会碰到的基础。
一、Unicode 字符集
JavaScript 源码以 Unicode 字符集编码。标识符与字符串字面量都可以直接使用非 ASCII 字符。
// 变量名可以使用 Unicode 字符
const 姓名 = \”张三\”;
const π = 3.14159;
const café = \”咖啡\”;
// 字符串中可以包含任意 Unicode 字符
const greeting = \”你好,世界!\”;
const emoji = \”😀\”;
const math = \”∑∫∂\”;
团队协作中通常仍使用英文标识符以保持可读性与一致性——这是风格约定,不是语言要求。
1.1 引擎支持的 Unicode 版本
| V8(Chrome / Node / Edge) | 跟随 ICU 更新 |
| SpiderMonkey(Firefox) | 跟随 ICU 更新 |
| JavaScriptCore(Safari) | 跟随 ICU 更新 |
规范不规定引擎必须支持哪一个 Unicode 版本。各引擎的实现细节随版本演进,因此不要把某个 Unicode 版本的属性支持(如较新的 \\p{…} 脚本名、Emoji 序列)当成可移植保证——需要时用特性检测。
1.2 Unicode 相关 API
// 码点
\”中\”.codePointAt(0); // 20013
String.fromCodePoint(20013); // \”中\”(ES2015)
// 码元(UTF-16 编码单元)
\”中\”.charCodeAt(0); // 20013
String.fromCharCode(20013); // \”中\”
// 规范化
\”café\”.normalize(\”NFC\”); // 规范化形式(ES2015)
// 大小写
\”Hello\”.toUpperCase(); // \”HELLO\”
\”Hello\”.toLowerCase(); // \”hello\”
这些方法属于 String,成员级语义见《2-标准库/03-String与RegExp》。本章只关心它们在词法层的用途:源码字符、字面量内容与标识符合法性。
二、转义序列
转义序列用于表示无法直接在源代码中输入的字符。能出现在正则、字符串与模板中的转义序列集合并不相同——见《2-标准库/03-String与RegExp》。
2.1 字符转义(Unicode)
| Unicode 转义(4 位十六进制) | \\uXXXX | \”\\u4E2D\” → \”中\” | BMP 内字符,范围 \\u0000 ~ \\uFFFF |
| Unicode 码点转义(大括号) | \\u{XXXXXX} | \”\\u{1F600}\” → \”😀\” | 任意 Unicode 码点,ES2015 引入 |
| 十六进制转义(Latin-1) | \\xXX | \”\\x48\” → \”H\” | 仅限 0x00 ~ 0xFF(编码单元值,不是字节) |
// 表示同一个字符\”中\”的两种方式
\”中\”; // 直接输入
\”\\u4E2D\”; // Unicode 转义
\”\\u{4E2D}\”; // Unicode 码点转义
// \\x 是\”编码单元值\”,不是 UTF-8 字节序列
\”\\x48\”; // \”H\”(U+0048)
\”\\xE4\”; // \”ä\”(U+00E4)—— 不是 UTF-8 首字节
// \”\\xE4\\xB8\\xAD\” 是三个 Latin-1 字符 \”ä¸\”,不等于 \”中\”
⚠️ \\xXX 是编码单元值,不是字节转义:它表示一个 UTF-16 编码单元的值,不接受字节序列;\”\\xE4\\xB8\\xAD\” 是 \”ä¸\”,不等于 \”中\”。要写 \”中\” 用 \”\\u4E2D\” 或 \”\\u{4E2D}\”。
2.2 字符串中的转义字符
| \\n | 换行(LF) | \\\\ | 反斜杠 |
| \\r | 回车(CR) | \\\’ | 单引号 |
| \\t | 制表符 | \\\” | 双引号 |
| \\b | 退格 | 反引号转义 | 反引号(模板字面量中) |
| \\f | 换页 | \\0 | NUL(后面不能紧跟十进制数字) |
| \\v | 垂直制表 |
const newline = \”第一行\\n第二行\”;
const tab = \”列1\\t列2\”;
const backslash = \”路径:C:\\\\Users\\\\John\”; // 每个反斜杠都要写两次
const quote = \”他说:\\\”你好\\\”\”;
2.3 无效与边界情形
// \”\\u{110000}\”; // SyntaxError:超出 Unicode 最大码点
\”\\u{10FFFF}\”; // 最大码点(合法)
// 代理对与码点转义等价
\”\\uD83D\\uDE00\”; // \”😀\”
\”\\u{1F600}\”; // \”😀\”(等价)
// 非转义字符(NonEscapeCharacter):\\ 后跟普通字符时,反斜杠被丢弃
\”\\U\”; // \”U\”(反斜杠被丢弃,不是保留字面反斜杠)
`C:\\Users\\John`; // \”C:UsersJohn\” ← 模板字面量同规则;要保留反斜杠用 String.raw 或 \\\\
String.raw`C:\\Users\\John`; // \”C:\\Users\\John\”(标签模板保留原始文本)
2.4 转义序列使用场景
| 嵌入特殊字符 | 换行、制表符等 |
| 编码非 ASCII 字符 | 在纯 ASCII 环境中 |
| 避免引号冲突 | 字符串中包含引号 |
| 表示不可见字符 | 控制字符 |
三、注释
3.1 单行注释与多行注释
// 这是一个单行注释
let x = 10; // 行尾注释
/*
* 这是一个多行注释
* 通常用于文件头说明、函数文档等
*/
function add(a, b) {
return a + b;
}
/* 多行注释也可以写成单行块的形式 */
3.2 注释不能嵌套
// 错误:多行注释不能嵌套
/*
外层注释
/* 内层注释 */
外层继续
*/
// 第一个 */ 就提前终止了注释,剩余部分成为代码 → SyntaxError
3.3 JSDoc 文档注释
/**
* 计算两个数的和
* @param {number} a – 第一个数
* @param {number} b – 第二个数
* @returns {number} 两数之和
*/
function add(a, b) {
return a + b;
}
/**
* 用户信息
* @typedef {Object} User
* @property {number} id – 用户 ID
* @property {string} name – 用户名
* @property {string} [email] – 邮箱(可选)
*/
/**
* 获取用户
* @param {number} id – 用户 ID
* @returns {Promise<User>} 用户信息
* @throws {NotFoundError} 用户不存在时抛出
*/
async function getUser(id) {
// …
}
| @param | 参数说明 | @example | 使用示例 |
| @returns | 返回值说明 | @deprecated | 标记已废弃 |
| @throws | 可能抛出的错误 | @see | 参考链接 |
| @typedef | 定义类型 | @since | 引入版本 |
| @property | 属性说明 | @author | 作者 |
JSDoc 不是 ECMA-262 的一部分,它是注释的书写约定,由 TypeScript / IDE / 文档工具解析。语法上它只是普通的多行注释。
3.4 注释规范
| 解释为什么,而非做什么 | 代码说明\”做什么\”,注释说明\”为什么\” |
| 避免冗余注释 | 不要注释显而易见的内容 |
| 及时更新 | 代码修改时同步更新注释 |
| 避免注释掉的代码 | 用版本控制管理历史 |
| 使用 JSDoc | 为公共 API 添加文档注释 |
let x = 10; // ❌ 冗余:\”将 x 设为 10\”
let timeout = 5000; // ✅ 解释原因:\”5 秒超时,根据 API 文档要求\”
四、字面量
字面量是在代码中直接表示值的语法结构。
4.1 字面量类型一览
| 数字字面量 | 42、3.14、0xFF、1e3、0b1010、1_000 | 整数、浮点、十六进制、科学计数法、二进制、数值分隔符 |
| BigInt 字面量 | 42n、0xFFn | ES2020 |
| 字符串字面量 | \”Hello\”、\’World\’ | 单引号/双引号 |
| 模板字面量 | `Hello ${name}` | ES2015 |
| 布尔字面量 | true、false | 布尔值 |
| null 字面量 | null | 表示空值 |
| 对象字面量 | { name: \”John\” } | 键值对集合 |
| 数组字面量 | [1, 2, 3] | 有序元素列表 |
| 正则表达式字面量 | /abc/g | 正则模式 |
⚠️ undefined 不是字面量。它是全局对象上不可写、不可配置的数据属性。见《01-类型系统》第三节。
4.2 数字字面量
// 整数与浮点
42;
–42;
3.14;
.5; // 0.5
5.; // 5.0
// 科学计数法
1e3; // 1000



