简介:这是一份面向前端开发者与JavaScript学习者的ECMAScript 6语言规范简体中文翻译资源,旨在降低阅读英文原版《ECMA-262 6th Edition》的门槛,适合希望深入理解ES6语法标准、查阅规范细节或参与翻译协作的技术人员。压缩包共18个文件,约6.66MB,以htm网页章节、png与jpg配图、svg矢量图、css样式表为主,另含pdf规范原文与md说明文档,整体按章节组织,便于逐节浏览与检索。目前已有262人学习下载。资源完整保留了规范正文的章节结构,从目录、范围与一致性说明到引言等模块均有覆盖,读者可对照中文译文与英文原版逐条研读,也可借助网页形式快速定位术语与语法定义,是理解ES6标准、参与规范翻译或做技术笔记的实用参考。
1. 一份把 ECMAScript 6 规范翻成中文的离线文档,到底能解决什么问题
很多人第一次打开 ECMA-262 的官方英文规范,翻不到三页就关掉了。不是英语不行,而是这份文档的写法本身就不是给人「读」的——它是一份形式化的语言定义,满屏的抽象操作、语法产生式、内部槽和完成记录,读起来像在啃一份编译器规格书。ecma262-6-cn这个资源做的事情很直接:把 ECMAScript 6(也就是 ES2015)那一版的规范正文翻译成中文,做成一份可以离线打开、按章节检索的 HTML 文档。它解决的不是「教你写 JS」的问题,而是当你在查let的暂时性死区到底怎么定义、Promise的 then 链在规范层面如何调度、解构赋值在遇到迭代器时走哪条抽象操作时,能有一份母语对照的权威文本摆在手边。
这份资源适合三类人:一是想搞清楚某个语法行为「为什么是这样」的中高级前端,二是需要对着规范写 polyfill 或 babel 插件的工具链开发者,三是准备做语言特性分享、需要引用规范原文的技术讲师。它不适合零基础学语法的人——规范不教你怎么用,只定义语言「是什么」。关键词里出现的 HTML,指的正是这份翻译最终以 HTML 文档形态组织,章节锚点、目录跳转、代码示例都在浏览器里直接看,不需要联网。
2. 规范文档的结构拆解:从语法产生式到抽象操作怎么读
2.1 先认清 ECMA-262 的章节骨架
ES6 规范的组织方式和你熟悉的 MDN 完全不同。它按「语言是什么」逐层定义,而不是按「你能用它做什么」来组织。整份文档大致分成这几块:前面是范围、一致性、规范性引用这类元信息;中间是记法约定(Notation)和词法语法(Lexical Grammar);核心部分是按语言结构展开的语义定义,从类型系统、类型转换,到表达式、语句、函数、类、模块;最后是标准库对象的定义,比如Array、String、Promise、Proxy、Reflect这些内建对象的方法签名和行为。
读这份翻译时,最容易迷路的地方是它大量使用「抽象操作」(Abstract Operation)来描述行为。比如你想知道Array.prototype.map到底怎么执行,规范不会给你一段伪代码了事,而是定义了一个叫Array.prototype.map的算法步骤,里面又调用IsCallable、CreateArrayFromList、LengthOfArrayLike这些更底层的抽象操作。这些操作在文档里都有独立编号和定义,读的时候要顺着编号跳,而不是指望一口气读完。
2.2 语法产生式和完成记录是两套必须分开看的语言
规范里有两套「元语言」,混在一起看必然晕。第一套是语法产生式,形如:
Statement : Block VariableStatement EmptyStatement ...这是用巴科斯范式描述「合法的代码长什么样」。第二套是算法步骤里的完成记录(Completion Record),形如ReturnIfAbrupt、?、!这些记号,描述「执行时怎么传递正常值和突然完成(break、continue、return、throw)」。
我一般建议的读法是:先只看语法产生式,确认某个写法在语法层面合不合法;再去看对应的运行时语义(Runtime Semantics)小节,那里才是真正定义行为的地方。翻译版在这两块都保留了原文的编号体系,所以你可以拿英文版对照着看,编号是对得上的。
2.3 用 HTML 文档做本地检索的具体做法
这份资源是 HTML 形态,落地用法就是把它放到本地,用浏览器打开,然后靠浏览器自带的页内查找(Ctrl+F)和目录锚点跳转来定位。如果你想要更强的检索能力,可以把它挂到一个本地静态服务器上,再用支持全文索引的工具建索引。常见做法是用 Python 起一个最简单的静态服务:
# 进入解压后的文档根目录 cd ecma262-6-cn # Python 3 起一个本地静态服务器,端口 8000 python3 -m http.server 8000 # 浏览器打开 http://localhost:8000/index.html这段命令的作用是把文档目录变成一个可访问的站点,避免直接用file://打开时部分相对路径锚点失效。参数说明:8000是端口,被占用就换8080或9000;http.server是 Python 标准库自带的模块,不需要额外装依赖。如果你更习惯 Node 环境,用npx serve也能达到同样效果。
提示:直接用
file://打开时,某些浏览器对本地 HTML 的锚点跳转和脚本执行有限制,起本地服务是最省事的规避方式。
2.4 对照英文原版做交叉验证
翻译版最大的价值是降低阅读门槛,但涉及精确语义时,我仍然建议对照英文原版。原因是规范里很多术语是「有定义的专有名词」,翻译过程中可能出现一词多译或译法不统一。比如Realm、Agent、Job、Completion这些词,在不同章节里如果译法不一致,会直接影响你对行为的理解。
交叉验证的做法很简单:在翻译版里定位到某个抽象操作的编号(比如7.3.xx这种),然后去 tc39 的官方仓库或 ECMA 官网下载对应版本的英文 PDF,按编号找到同一节。两边对照着读,遇到译法可疑的地方以英文定义为准。这不是说翻译不可靠,而是规范这种文本,术语的精确性比可读性更重要。
3. 把规范用起来:查一个具体特性的完整流程
3.1 以 let 的暂时性死区为例走一遍
假设你想搞清楚「为什么在let声明之前访问变量会抛 ReferenceError」。在翻译版里,你要找的不是「let 教程」,而是这几处:13.3.1 Let and Const Declarations的运行时语义,以及8.1.1.1附近关于环境记录(Environment Record)和绑定(Binding)的定义。
流程是这样的:先看let声明的求值算法,它会调用InitializeBinding把变量绑定到当前环境记录,但绑定的初始化时机和声明的实例化时机是分开的。声明实例化(Instantiation)阶段会创建绑定但标记为「未初始化」,只有执行到声明语句时才真正初始化。在初始化之前访问,GetBindingValue会检查绑定状态,发现未初始化就抛 ReferenceError。这就是暂时性死区的规范来源。
3.2 用规范定义反推 polyfill 的边界
如果你要写一个模拟let块级作用域的 polyfill,规范读到这里就能得出一个关键结论:真正的块级作用域和暂时性死区,靠var加闭包是模拟不完整的,因为var没有「未初始化绑定」这个状态。这就是为什么 babel 转let时会引入_temporalRef这类辅助函数,而不是简单替换成var。
// babel 风格的暂时性死区检查辅助函数(简化示意) function _temporalRef(val, name) { // 如果访问时绑定仍处于未初始化状态,抛错 if (val === _temporalUndefined) { throw new ReferenceError(name + " is not defined - temporal dead zone"); } return val; } // 声明时先赋一个哨兵值,代表「未初始化」 var _temporalUndefined = {};这段代码的逻辑是:用一个哨兵对象代表「已创建但未初始化」的绑定状态,访问时先比对哨兵,命中就抛 ReferenceError。参数说明:val是当前读取到的值,name是变量名用于报错信息。这个模式直接对应规范里GetBindingValue对未初始化绑定的处理,理解了规范,你才知道 polyfill 为什么必须多这一层。
3.3 查标准库方法时的定位技巧
查Promise、Proxy、Reflect这类标准库对象,直接跳到文档后半部分的「标准库」章节。每个内建对象都有固定的组织顺序:先是该对象的内部槽和内部方法,然后是构造函数属性,再是原型对象属性,最后是实例属性。比如查Promise.prototype.then,你会看到它定义了PerformPromiseThen这个抽象操作,里面涉及 Promise 的状态、反应记录(PromiseReaction)的挂载和 Job 的入队。
这里有个容易翻车的点:规范里的 Promise 行为是异步调度的,then的回调不是立即执行,而是通过EnqueueJob放进 Job 队列。如果你只读then那一节,可能会以为回调是同步的。必须顺着EnqueueJob和RunJobs去看,才能理解微任务的调度时机。这也是为什么规范要按抽象操作层层引用,而不是在一节里讲完。
4. 避坑与常见问题:读规范翻译版容易踩的五个坑
4.1 把翻译版当唯一依据,术语对不上
现象:读到某个抽象操作,翻译版用的词和你在英文社区看到的对不上,导致搜不到相关资料。原因:规范术语的翻译没有强制统一标准,不同章节可能用不同译法。解决:记住英文原词,用英文词去搜。比如「完成记录」对应 Completion Record,「环境记录」对应 Environment Record,遇到不确定的术语,回英文版确认后再检索。
4.2 跳过记法约定直接读正文
现象:看到?、!、ReturnIfAbrupt这些记号完全不知道什么意思,读几页就放弃。原因:这些记号在文档开头的「记法约定」章节有统一定义,跳过它等于没拿钥匙就进门。解决:先花二十分钟把记法约定那一章读完,搞清楚?表示「如果是突然完成就返回」,!表示「断言不是突然完成」,后面读起来会顺很多。
4.3 用读 MDN 的方式读规范
现象:想查「怎么用 Array.map」,翻规范翻了半天没找到用法示例。原因:规范不提供用法示例,它只定义行为。解决:用法查 MDN,行为查规范。两者分工不同,别指望规范教你写代码。规范回答的是「这个方法在语言层面被定义成什么样」,不是「我该怎么用它」。
4.4 忽略版本差异,拿 ES6 规范查 ES2020 的特性
现象:想查可选链?.或空值合并??,在 ES6 规范里怎么都找不到。原因:这份翻译对应的是 ES6(2015)那一版,后续版本新增的特性不在其中。解决:确认你要查的特性属于哪个版本。ES6 之后每年都有新版本,可选链是 ES2020,Array.prototype.at是 ES2022。查新特性要去对应年份的规范,或者用 tc39 的提案仓库。
4.5 本地打开锚点失效,以为文档损坏
现象:双击 HTML 文件打开,点目录跳转没反应,或者部分章节显示异常。原因:浏览器对file://协议下的本地文件有安全限制,相对路径和脚本可能不执行。解决:起一个本地静态服务器再访问,参考 2.3 节的命令。如果还是有问题,检查解压是否完整,HTML 依赖的资源文件是否都在同一目录树下。
5. 进阶用法:把规范文档变成可检索的本地知识库
读到这里,你应该已经能把这份翻译版当工具用了。但如果你像我一样,经常需要在规范里反复查同一个概念,单靠浏览器 Ctrl+F 效率还是低。我一般会做一步额外处理:把 HTML 文档转成纯文本,建一个本地全文索引,用命令行工具检索。这样查一个术语,能一次性看到它在所有章节里的出现位置。
具体做法分两步。第一步,用 Python 把 HTML 抽成文本,按章节切块:
from bs4 import BeautifulSoup import os, json # 遍历文档目录,抽取每个 HTML 的正文文本 chunks = [] for root, dirs, files in os.walk("ecma262-6-cn"): for f in files: if f.endswith(".html"): path = os.path.join(root, f) with open(path, encoding="utf-8") as fp: soup = BeautifulSoup(fp.read(), "html.parser") # 按标题切块,保留章节号作为定位信息 for h in soup.find_all(["h1", "h2", "h3"]): title = h.get_text(strip=True) body = [] for sib in h.find_next_siblings(): if sib.name in ["h1", "h2", "h3"]: break body.append(sib.get_text(" ", strip=True)) chunks.append({"title": title, "text": " ".join(body), "file": path}) # 落成一个 JSON,供后续检索 with open("spec_index.json", "w", encoding="utf-8") as fp: json.dump(chunks, fp, ensure_ascii=False)这段脚本的逻辑是:遍历所有 HTML 文件,用 BeautifulSoup 解析,按标题层级把正文切成块,每块记录标题、正文和来源文件。参数说明:find_all(["h1","h2","h3"])决定切块粒度,想更细可以加上h4;find_next_siblings用来收集当前标题到下一个标题之间的内容。跑完会得到一个spec_index.json,里面是结构化的章节文本。
第二步,用这个索引做检索。最省事的方式是写个简单的关键词匹配脚本,或者直接上ripgrep对抽出来的文本文件做全文搜索:
# 把 JSON 里的文本导出成纯文本后,用 ripgrep 检索 # 查所有提到「暂时性死区」或 temporal dead zone 的章节 rg -n "暂时性死区|temporal dead zone" spec_text/rg的-n参数是显示行号,方便你回到原文定位。如果你想要更智能的语义检索,可以把每个 chunk 做一次向量化,用本地向量库建索引,但那是另一个话题了,对查规范来说,关键词检索已经够用。
这套流程跑通之后,我查规范的习惯就变了:不再是一页页翻,而是先搜关键词拿到候选章节,再回原文精读。规范这种文本,检索能力比阅读速度重要得多。从那以后我每次读规范,都强制先建好索引再动手,省下来的时间远超搭索引的那点成本。希望帮到你。
本文还有配套的精品资源,点击获取