JEP 292: Implement Selected ECMAScript 6 Features in Nashorn | 在 Nashorn 中实现选择的 ECMAScript 6 功能
摘要
在 Nashorn 中实现一组选定的 ECMA-262 第 6 版(也称为 ECMAScript 6 或 ES6)引入的许多 新功能。
目标
在 JDK 9 中正确实现 ES6 的大量功能。
由于这是一个庞大的工作,我们需要分几个步骤来实现 ES6,其中 JDK 9 只是第一步。剩下的 ES6 功能可能会在 JDK 9 的更新版本和未来的主要 JDK 版本中实现。
动机
ECMAScript 6 于 2015 年 6 月发布。迄今为止,没有任何 JavaScript 引擎完全支持 ES6,但包括 Google V8、Mozilla Spidermonkey 和 JavaScriptCore 在内的主要引擎最近在 实现 ES6 方面取得了重大进展。
我们从 JDK 8u40 开始使用 Nashorn 实现 ES6 中的 JEP 203(let
和 const
)。为了跟上其他引擎的步伐,我们计划在 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
- 符号
- 二进制和八进制字面量
其他功能已经进行了部分原型开发,并且在有限的时间内可能完成。这些功能有望包含在 JDK 9 的更新版本中:
- 箭头函数
- 增强的对象字面量
- 解构赋值
- 默认参数、剩余参数和扩展参数
- Unicode
- 可子类化的内建对象
- Promises
- 代理
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 版本。初步结果是令人鼓舞的。然而,由于许多测试要求完整的 ES6 实现,因此将 ES5.1 版本的 test262 切换为我们的主要测试套件是不可行的。
在开发和集成本 JEP 时,我们将依赖于 ES6 版本的 test262 来发现错误并填补缺失的部分。计划在接近完全 ES6 功能时将 ES6 版本作为我们的主要 ES6 测试套件。
风险和假设
ECMAScript 6 规范已经发布,其中的大部分已在各种 JavaScript 引擎中实现,因此不再存在移动规范或规范文本的歧义风险。
我们对功能的优先级排序可能会忽略一些开发者需要的功能。然而,提出的迭代方法确保随着时间的推移交付所有缺失的功能。
依赖关系
ES6 内部各个功能之间存在依赖关系,并且我们选择按照复杂性递增的顺序来处理这些特性。