如词不达意,欢迎提 PR & issue
采用中英混排的方式进行译制,如不解请查看对应原文
本文档将与原作者的 文档 保持同步更新,欢迎关注
ECMAScript 6 is the upcoming version of the ECMAScript standard. This standard is targeting ratification in June 2015. ES6 is a significant update to the language, and the first update to the language since ES5 was standardized in 2009. Implementation of these features in major JavaScript engines is underway now.
ECMAScript 6 是 ECMAScript 的下一代标准,预计将在 2015年6月 正式发布。ES6 的发布将是这门语言自2009年 ES5 正式发布以来的首次更新,是一次富有意义的更新。主流Javascript引擎中的这些新特性正在开发中。
See the draft ES6 standard for full specification of the ECMAScript 6 language.
若希望阅读 ECMAScript 6 语言的完整规范,请参见ES6标准草案。
ES6 includes the following new features:
ES6 包含了以下这些新特性:
- Arrows 箭头函数
- classes 类
- enhanced object literals 增强的对象字面量
- template strings 模板字符串
- destructuring 解构
- default + rest + spread 默认值+多余参数组合+参数伸展
- let + const let + const 操作符
- iterators + for..of 迭代器 + for...of
- generators 生成器
- unicode 统一码
- modules 模块
- module loaders 模块加载器
- map + set + weakmap + weakset 数据结构
- proxies 代理
- symbols 符号
- subclassable built-ins 可子类化内建对象
- promises 对象
- math + number + string + object APIs
- binary and octal literals 二进制和八进制字面量
- reflect api 反射API
- tail calls 尾调用
Arrows are a function shorthand using the =>
syntax. They are syntactically similar to the related feature in C#, Java 8 and CoffeeScript. They support both expression and statement bodies. Unlike functions, arrows share the same lexical this as their surrounding code.
箭头函数是使用=>
语法的函数简写形式。这在语法上与 C#、Java 8 和 CoffeeScript 的相关特性非常相似。它们同时支持表达式体和语句体。与(普通的)函数所不同的是,箭头函数和其上下文中的代码共享同一个具有词法作用域的this
。
// Expression bodies
// 表达式体
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
var pairs = evens.map(v => ({even: v, odd: v + 1}));
// Statement bodies
// 语句体
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
// Lexical this
// 具有词法作用域的 this
var bob = {
_name: "Bob",
_friends: ["Amy", "Bob", "Cinne", "Dylan", "Ellen"],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
}
ES6 classes are a simple sugar over the prototype-based OO pattern. Having a single convenient declarative form makes class patterns easier to use, and encourages interoperability. Classes support prototype-based inheritance, super calls, instance and static methods and constructors.
ES6 的类是在基于原型的面向对象模式之上的简单语法糖,它有唯一的、便捷的声明形式,这使得类模式更容易使用,并且鼓励了互操作性。class定义的类支持基于原型的继承、super 调用、实例和静态方法以及构造函数。
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
get boneCount() {
return this.bones.length;
}
set matrixType(matrixType) {
this.idMatrix = SkinnedMesh[matrixType]();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
Object literals are extended to support setting the prototype at construction, shorthand for foo: foo assignments, defining methods, making super calls, and computing property names with expressions. Together, these also bring object literals and class declarations closer together, and let object-based design benefit from some of the same conveniences.
对象字面量被扩展以支持以下特性:在构建的时候设置原型、foo: foo
赋值的简写形式、定义方法、进行super 调用以及使用表达式计算属性名称等。这样就使得对象字面量和类的声明的联系更加紧密,使得基于对象的设计更加便利。
var obj = {
// __proto__
__proto__: theProtoObj,
// Shorthand for ‘handler: handler’
// ‘handler: handler’ 的简写形式
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names
// 计算所得的(动态的)属性名称
[ 'prop_' + (() => 42)() ]: 42
};
Template strings provide syntactic sugar for constructing strings. This is similar to string interpolation features in Perl, Python and more. Optionally, a tag can be added to allow the string construction to be customized, avoiding injection attacks or constructing higher level data structures from string contents.
模板字符串提供构造字符串的语法糖,这与Perl、Python等许多语言中的字符串插值功能非常相似,你也可以通过添加标签(tag)来自定义构造字符串,避免注入攻击,或者基于字符串构建更高层次的数据结构。
// Basic literal string creation
// 基础字符串字面量的创建
`In JavaScript '\n' is a line-feed.`
// Multiline strings
// 多行字符串
`In JavaScript this is
not legal.`
// String interpolation
// 字符串插值
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
// Construct an HTTP request prefix is used to interpret the replacements and construction
// 构造一个HTTP请求前缀用来解释替换和构造,大意就是可以构造一个通用的HTTP prefix并通过赋值生成最终的HTTP请求
GET`http://foo.org/bar?a=${a}&b=${b}
Content-Type: application/json
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}`(myOnReadyStateChangeHandler);
Destructuring allows binding using pattern matching, with support for matching arrays and objects. Destructuring is fail-soft, similar to standard object lookup foo["bar"]
, producing undefined
values when not found.
解构允许在(变量-值)绑定时使用模式匹配,支持匹配数组和对象,解构支持失效弱化,与标准的对象查询foo["bar"]
相似,当查询无结果时生成undefined
值。
// list matching
// 列表匹配
var [a, , b] = [1,2,3];
// object matching
// 对象匹配
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode()
// object matching shorthand
// binds `op`, `lhs` and `rhs` in scope
// 对象匹配简写形式
var {op, lhs, rhs} = getASTNode()
// 上面作者给的示例看得云里雾里的,这里我再给出一个
function today() { return { d: 2, m: 3, y: 2015 }; }
var { m: month, y: year } = today(); // month = 3, year = 2015
// Can be used in parameter position
// 也可以作为参数使用
function g({name: x}) {
console.log(x);
}
g({name: 5})
// Fail-soft destructuring
// 失效弱化解构,结果查询不到时定义为 undefined
var [a] = [];
a === undefined;
// Fail-soft destructuring with defaults
// 具备默认值的失效弱化解构
var [a = 1] = [];
a === 1;
Callee-evaluated default parameter values. Turn an array into consecutive arguments in a function call. Bind trailing parameters to an array. Rest replaces the need for arguments
and addresses common cases more directly.
支持由被调用函数进行求值的参数默认值。
在函数调用时使用...
运算符,可以将作为参数的数组拆解为连续的多个参数。
在函数定义时使用...
运算符,则可以将函数尾部的多个参数绑定到一个数组中。
“多余参数组合”取代了arguments
,并可更直接地应用于通常的用例中。
function f(x, y=12) {
// y is 12 if not passed (or passed as undefined)
return x + y;
}
f(3) == 15
function f(x, ...y) {
// y is an Array
return x * y.length;
}
f(3, "hello", true) == 6
function f(x, y, z) {
return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) == 6
Block-scoped binding constructs. let
is the new var
. const
is single-assignment. Static restrictions prevent use before assignment.
let 和 const 是具有块级作用域的绑定用构造,let
是新的 var
,只在块级作用域内有效,const
是单赋值,声明的是块级作用域的常量。此两种操作符具有静态限制,可以防止出现“在赋值之前使用”的错误。
function f() {
{
let x;
{
// okay, block scoped name
const x = "sneaky";
// error, const
x = "foo";
}
// error, already declared in block
let x = "inner";
}
}
Iterator objects enable custom iteration like CLR IEnumerable or Java Iterable. Generalize for..in
to custom iterator-based iteration with for..of
. Don’t require realizing an array, enabling lazy design patterns like LINQ.
迭代器对象允许像 CLI IEnumerable 或者 Java Iterable 一样自定义迭代器。将for..in
转换为自定义的基于迭代器的形如for..of
的迭代,不需要实现一个数组,支持像 LINQ 一样的惰性设计模式
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return { done: false, value: cur }
}
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
console.log(n);
}
Iteration is based on these duck-typed interfaces (using TypeScript type syntax for exposition only):
迭代器基于这些鸭子类型的接口 (此处使用TypeScript 的类型语法,仅用于阐述问题):
interface IteratorResult {
done: boolean;
value: any;
}
interface Iterator {
next(): IteratorResult;
}
interface Iterable {
[Symbol.iterator](): Iterator
}
Generators simplify iterator-authoring using function*
and yield
. A function declared as function* returns a Generator instance. Generators are subtypes of iterators which include additional next
and throw
. These enable values to flow back into the generator, so yield
is an expression form which returns a value (or throws).
生成器通过使用function*
和yield
简化迭代器的编写, 形如function*的函数声明返回一个生成器实例,生成器是迭代器的子类型,迭代器包括附加的next
和throw
,这使得值可以回流到生成器中,所以,yield
是一个返回或抛出值的表达式形式。
Note: Can also be used to enable ‘await’-like async programming, see also ES7 await
proposal.
注意:也可以被用作类似‘await’一样的异步编程中,具体细节查看ES7的await
提案
var fibonacci = {
[Symbol.iterator]: function*() {
var pre = 0, cur = 1;
for (;;) {
var temp = pre;
pre = cur;
cur += temp;
yield cur;
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
console.log(n);
}
The generator interface is (using TypeScript type syntax for exposition only): 生成器接口如下(此处使用TypeScript 的类型语法,仅用于阐述问题):
interface Generator extends Iterator {
next(value?: any): IteratorResult;
throw(exception: any);
}
Non-breaking additions to support full Unicode, including new Unicode literal form in strings and new RegExp u
mode to handle code points, as well as new APIs to process strings at the 21bit code points level. These additions support building global apps in JavaScript.
Non-breaking additions to support full Unicode
~~这句看了半天不知道作者想要表达什么,我就查了下资料,有一种可能是: 增加不换行空格的特性以全面支持Unicode,还有一种可能是:~~渐进增强地、非破坏性地全面支持Unicode,也就是说,新加入的特性并不影响老的代码的使用。我个人比较倾向于第二种解读。@sumhat提示说第二种解读是正确的
(续)字符串支持新的Unicode文本形式,也增加了新的正则表达式修饰符u
来处理代码点,同时,新的API可以在21bit代码点级别上处理字符串,增加这些支持后可以使用 Javascript 构建全球化的应用。
注:关于Unicode推荐阅读复杂的Unicode,疑惑的Python
// same as ES5.1
// 与 ES5.1 相同
"𠮷".length == 2
// new RegExp behaviour, opt-in ‘u’
// 新的正则表达式行为,使用可选的‘u’修饰符
"𠮷".match(/./u)[0].length == 2
// new form
// ES5.1的写法是`反斜杠+u+码点`,新的形式可以通过添加一组大括号`{}`来表示超过四字节的码点
"\u{20BB7}"=="𠮷"=="\uD842\uDFB7"
// new String ops
// 新的字符串处理方法
"𠮷".codePointAt(0) == 0x20BB7
// for-of iterates code points
// foo-of 以代码点为单位进行迭代
for(var c of "𠮷") {
console.log(c);
}
Language-level support for modules for component definition. Codifies patterns from popular JavaScript module loaders (AMD, CommonJS). Runtime behaviour defined by a host-defined default loader. Implicitly async model – no code executes until requested modules are available and processed.
ES6 在语言层面上支持使用模块来进行组件定义,将流行的JavaScript模块加载器(AMD、CommonJS)中的模式固化到了语言中。运行时行为由宿主定义的默认加载器定义,隐式异步模型 - 直到(全部)请求的模块均可用且经处理后,才会执行(当前模块内的)代码。
// lib/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
// app.js
import * as math from "lib/math";
alert("2π = " + math.sum(math.pi, math.pi));
// otherApp.js
import {sum, pi} from "lib/math";
alert("2π = " + sum(pi, pi));
Some additional features include export default
and export *
:
额外的新特性,包括export default
以及export *
:
// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
// app.js
import exp, {pi, e} from "lib/mathplusplus";
alert("2π = " + exp(pi, e));
Module loaders support:
- Dynamic loading
- State isolation
- Global namespace isolation
- Compilation hooks
- Nested virtualization
模块加载器支持:
- 动态加载
- 状态隔离
- 全局命名空间隔离
- 编译钩子
- 嵌套虚拟化(注: 在模块内调用模块)
The default module loader can be configured, and new loaders can be constructed to evaluate and load code in isolated or constrained contexts.
默认的模块加载器是可配置的,也可以构建新的加载器,对在隔离和受限上下文中的代码进行求值和加载。
// Dynamic loading – ‘System’ is default loader
// 动态加载 - ‘System’ 是默认的加载器
System.import('lib/math').then(function(m) {
alert("2π = " + m.sum(m.pi, m.pi));
});
// Create execution sandboxes – new Loaders
// 创建一个执行沙箱- 新的加载器
var loader = new Loader({
global: fixup(window) // replace ‘console.log’
});
loader.eval("console.log('hello world!');");
// Directly manipulate module cache
// 直接操作模块缓存
System.get('jquery');
System.set('jquery', Module({$: $})); // WARNING: not yet finalized 警告:此部分的设计尚未最终定稿
Efficient data structures for common algorithms. WeakMaps provides leak-free object-key’d side tables. 用于实现常见算法的高效数据结构,WeakMaps提供不会泄露的对象键(对象作为键名,而且键名指向对象)索引表 注:所谓的不会泄露,指的是对应的对象可能会被自动回收,回收后WeakMaps自动移除对应的键值对,有助于防止内存泄露
// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;
// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;
// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined
// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });
// Because the added object has no other references, it will not be held in the set
// 由于所加入的对象没有其他引用,故在此集合内不会保留之。
Proxies enable creation of objects with the full range of behaviors available to host objects. Can be used for interception, object virtualization, logging/profiling, etc.
代理可以创造一个具备宿主对象全部可用行为的对象。可用于拦截、对象虚拟化、日志/分析等。
// Proxying a normal object
// 代理一个普通对象
var target = {};
var handler = {
get: function (receiver, name) {
return `Hello, ${name}!`;
}
};
var p = new Proxy(target, handler);
p.world === 'Hello, world!';
// Proxying a function object
// 代理一个函数对象
var target = function () { return 'I am the target'; };
var handler = {
apply: function (receiver, ...args) {
return 'I am the proxy';
}
};
var p = new Proxy(target, handler);
p() === 'I am the proxy';
There are traps available for all of the runtime-level meta-operations:
所有运行时级别的元操作都有对应的陷阱(使得这些操作都可以被代理):
var handler =
{
get:...,
set:...,
has:...,
deleteProperty:...,
apply:...,
construct:...,
getOwnPropertyDescriptor:...,
defineProperty:...,
getPrototypeOf:...,
setPrototypeOf:...,
enumerate:...,
ownKeys:...,
preventExtensions:...,
isExtensible:...
}
Symbols enable access control for object state. Symbols allow properties to be keyed by either string
(as in ES5) or symbol
. Symbols are a new primitive type. Optional name
parameter used in debugging - but is not part of identity. Symbols are unique (like gensym), but not private since they are exposed via reflection features like Object.getOwnPropertySymbols
.
符号(Symbol) 能够实现针对对象状态的访问控制,允许使用string
(与ES5相同)或symbol
作为键来访问属性。符号是一个新的原语类型,可选的name
参数可以用于调试——但并不是符号身份的一部分。符号是独一无二的(如同gensym(所产生的符号)),但不是私有的,因为它们可以通过类似Object.getOwnPropertySymbols
的反射特性暴露出来。
var MyClass = (function() {
// module scoped symbol
// 具有模块作用域的符号
var key = Symbol("key");
function MyClass(privateData) {
this[key] = privateData;
}
MyClass.prototype = {
doStuff: function() {
... this[key] ...
}
};
return MyClass;
})();
var c = new MyClass("hello")
c["key"] === undefined
Subclassable Built-ins 可子类化的内建对象
In ES6, built-ins like Array
, Date
and DOM Element
s can be subclassed.
在 ES6 中,内建对象,如Array
、Date
以及DOM元素
可以被子类化。
Object construction for a function named Ctor
now uses two-phases (both virtually dispatched):
- Call
Ctor[@@create]
to allocate the object, installing any special behavior - Invoke constructor on new instance to initialize
针对名为Ctor
的函数,其对应的对象的构造现在分为两个阶段(这两个阶段都使用虚分派):
- 调用
Ctor[@@create]
为对象分配空间,并插入特殊的行为 - 在新实例上调用构造函数来进行初始化
The known @@create
symbol is available via Symbol.create
. Built-ins now expose their @@create
explicitly.
已知的@@create
符号可以通过Symbol.create
来使用,内建对象现在显式暴露它们的@@create
。
// Pseudo-code of Array
// Array伪代码
class Array {
constructor(...args) { /* ... */ }
static [Symbol.create]() {
// Install special [[DefineOwnProperty]]
// to magically update 'length'
}
}
// User code of Array subclass
// Array子类的用户代码
class MyArray extends Array {
constructor(...args) { super(...args); }
}
// Two-phase 'new':
// 1) Call @@create to allocate object
// 2) Invoke constructor on new instance
// 两阶段的'new':
// 1) 调用@@create来为对象分配空间
// 2) 在新实例上调用构造函数
var arr = new MyArray();
arr[1] = 12;
arr.length == 2
Many new library additions, including core Math libraries, Array conversion helpers, and Object.assign for copying.
新加入了许多库,包括核心数学库,进行数组转换的协助函数,以及用来进行拷贝的Object.assign。
Number.EPSILON
Number.isInteger(Infinity) // false
Number.isNaN("NaN") // false
Math.acosh(3) // 1.762747174039086
Math.hypot(3, 4) // 5
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
"abcde".includes("cd") // true
"abc".repeat(3) // "abcabcabc"
Array.from(document.querySelectorAll('*')) // Returns a real Array 返回一个真正的Array
Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior 与Array(...)类似,但只有一个参数时,并不会有特殊行为。
[0, 0, 0].fill(7, 1) // [0,7,7]
[1, 2, 3].find(x => x == 3) // 3
[1,2,3].findIndex(x => x == 2) // 1
["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys() // iterator 0, 1, 2
["a", "b", "c"].values() // iterator "a", "b", "c"
Object.assign(Point, { origin: new Point(0,0) })
Two new numeric literal forms are added for binary (b
) and octal (o
).
加入对二进制(b
)和八进制(o
)字面量的支持。
0b111110111 === 503 // true
0o767 === 503 // true
Promises are a library for asynchronous programming. Promises are a first class representation of a value that may be made available in the future. Promises are used in many existing JavaScript libraries.
Promise是用来进行异步编程的库。Promise是对一个“将来可能会变得可用”的值的第一类表示,Promise被使用在现有的许多JavaScript库中。
function timeout(duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration);
})
}
var p = timeout(1000).then(() => {
return timeout(2000);
}).then(() => {
throw new Error("hmm");
}).catch(err => {
return Promise.all([timeout(100), timeout(200)]);
})
Full reflection API exposing the runtime-level meta-operations on objects. This is effectively the inverse of the Proxy API, and allows making calls corresponding to the same meta-operations as the proxy traps. Especially useful for implementing proxies.
完整的反射API。此API在对象上暴露了运行时级别的元操作,从效果上来说,这是一个反代理API,并允许调用与代理陷阱中相同的元操作。实现代理非常有用。
// No sample yet
Calls in tail-position are guaranteed to not grow the stack unboundedly. Makes recursive algorithms safe in the face of unbounded inputs.
(ES6)保证尾部调用时栈不会无限增长,这使得递归算法在面对未作限制的输入时,能够安全地执行。
function factorial(n, acc = 1) {
'use strict';
if (n <= 1) return acc;
return factorial(n - 1, n * acc);
}
// Stack overflow in most implementations today,
// but safe on arbitrary inputs in ES6
// 栈溢出存在于现在绝大多数的实现中,
// 但是在 ES6 中,针对任意的输入都很安全
factorial(100000)
编程语言进化到现阶段沉淀了许多成熟方案,例如接口,duck-typed,映射等等,还有许多不明觉厉的概念,每个语言都争相支持这些语言设计的新方案,所以 ES6 的一部分特性看起来很像 Go