JEP 292:在 Nashorn 中实现选定的 ECMAScript 6 特性
概述
在 Nashorn 中实现 ECMA-262 第 6 版(也称为 ECMAScript 6 或简称 ES6)引入的许多 新特性 中选定的一部分。
目标
在 JDK 9 的 Nashorn 中正确实现大量的 ES6 特性。
由于这项任务的规模庞大,我们需要分几个步骤来交付 ES6,其中 JDK 9 将只是第一步。剩余的 ES6 功能可能会在 JDK 9 的更新版本和未来的主要 JDK 版本中交付。
动机
ECMAScript 6 于 2015 年 6 月发布。目前还没有任何 JavaScript 引擎完全支持 ES6,但包括 Google V8、Mozilla Spidermonkey 和 JavaScriptCore 在内的主流引擎最近在 ES6 的实现 方面取得了重大进展。
我们在 Nashorn 中通过 JEP 203(let
和 const
)开始在 JDK 8u40 中实现 ES6。为了跟上其他引擎的步伐,我们计划在 JDK 9 中增加对 ECMAScript 6 特性的重要子集的支持。
描述
ECMAScript 6 包含以下新特性:
-
箭头函数:一种使用
=>
语法定义函数的简洁方式 -
类:一种使用继承、构造函数和方法来定义类的方式
-
增强的对象字面量:支持特殊和计算属性键
-
模板字符串:动态求值的多行字符串
-
解构赋值:使用对象或数组语法进行赋值绑定
-
默认参数、剩余参数和扩展参数:更灵活的参数传递方式
-
let
、const
和块级作用域:块级作用域的变量和常量声明 -
迭代器和
for..of
循环:用于遍历任意对象的协议 -
生成器:一种用于创建迭代器的特殊函数
-
Unicode:具有向后兼容性的完整 Unicode 支持
-
模块:语言级别的模块定义支持
-
模块加载器:支持动态加载、隔离和编译挂钩
-
Map
、Set
、WeakMap
和WeakSet
:各种新的集合类 -
代理:允许创建具有特殊行为的对象
-
符号:一种新的唯一属性键类型
-
可子类化的内置对象:如
Array
和Date
等内置对象可以被子类化 -
Promises:用于异步未来完成的 API
-
Math
、Number
、String
和Object
API:内置对象上的各种新函数 -
二进制和八进制字面量:数字字面量的新形式
-
反射 API:用于执行元编程操作的 API
-
尾调用:允许递归代码而不会导致无限制的栈增长
在这些特性中,我们已经在 JDK 8u40 中实现了 let
、const
和块级作用域,对应的是 JEP 203。其他一些特性已经被原型化,并应加入到 JDK 9 初始发布版本所支持的 ES6 特性列表中。这些特性包括以下内容:
- 模板字符串
let
、const
和块级作用域- 迭代器和
for..of
循环 Map
、Set
、WeakMap
和WeakSet
- 符号(Symbols)
- 二进制和八进制字面量
其他功能已部分制作出原型,似乎有可能在有限的时间内完成。这些是包含在 JDK 9 更新版本中的候选功能:
- 箭头函数
- 增强的对象字面量
- 解构赋值
- 默认参数、剩余参数和展开参数
- Unicode
- 可子类化的内置对象
- Promises
- Proxies
Math
、Number
、String
和Object
API- 反射 API
其余特性涉及的内容更多,可能需要更长的实现时间。虽然在 JDK 9 的更新版本中包含其中某些内容或许可行,但我们目前计划将它们定位到未来的主版本 JDK 发布中。这些特性包括:
- 类
- 生成器
- 模块
- 模块加载器
- 尾调用
尽管实现了 ES6 功能,JDK 9 的 Nashorn 代码库中的 Nashorn 解析器已经支持 ES6 语法更改。
替代方案
我们可以选择暂时忽略 ECMAScript 6,而不是采用这里提出的迭代方法,并且转而专注于改进我们现有的基于 ECMAScript 5 的实现。
或者,我们可以尝试一次性实现 ES6。然而,这样做会阻止我们及早获得反馈并发现错误。此外,ES6 中新特性的规模和数量使得这种方法不切实际。
不向 ES6 做出任何努力会是一个错误,而且会给用户与客户传递错误的信息。
测试
作为实施 ES6 部分内容的工作的一部分,我们开发了一个基本的功能测试集,它将成为 JEP 的一部分。
同时,我们也已经开始运行官方的 ECMAScript 一致性测试套件 test262 的 ES6 版本。初步结果令人鼓舞。然而,将我们的主要测试套件从 ES5.1 版本的 test262 切换到 ES6 版本并不可行,因为许多测试需要一个完整的 ES6 实现。
在开发和集成此 JEP 的过程中,我们将依赖 test262 的 ES6 版本来发现错误并填补缺失的部分。计划是当我们接近完整的 ES6 功能时,切换到 ES6 版本作为我们的主要 ES6 测试套件。
风险与假设
ECMAScript 6 规范已经发布,并且其中的很大一部分已经在各种 JavaScript 引擎中得到了实现,因此不再存在规范变动或规范文本中存在歧义的风险。
我们对功能的优先排序可能忽略了开发人员需要的某些功能。然而,这种建议的迭代方法确保了所有缺失的功能会随着时间的推移而得到交付。
依赖
ES6 中的各种特性之间存在依赖关系,我们的实现顺序是按照复杂性递增的顺序来安排的。