学习 ES2015
本文档最初是从 Luke Hoban 的 es6features 仓库转载的。请到 GitHub 上给他 点个赞吧!
强烈建议在 REPL 上尝试这些新功能。
简介
ECMAScript 2015 是一个 ECMAScript 标准,于 2015 年 6 月批准。
ES2015 是对 JavaScript 编程语言的重要更新,也是自 2009 年 ES5 标准化以来对该语言的首次重大更新。主流 JavaScript 引擎对这些新特性的实现 正在进行中。
参考 ES2015 标准 了解 ECMAScript 2015 的完整规范。
ECMAScript 2015 特性
箭头函数与 Lexical This
箭头函数是使用 =>
语法的函数简写方式。他们在语法上
与 C#、Java 8 和 CoffeeScript 中的相关功能类似。他们都支持
表达式和both expression and statement bodies. Unlike functions, arrows share the same
lexical this
as their surrounding code. If an arrow is inside another function,
it shares the "arguments" variable of its parent function.
// Expression bodies
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
// Statement bodies
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
// Lexical this
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
};
// Lexical arguments
function square() {
let example = () => {
let numbers = [];
for (let number of arguments) {
numbers.push(number * number);
}
return numbers;
};
return example();
}
square(2, 4, 7.5, 8, 11.5, 21); // returns: [4, 16, 56.25, 64, 132.25, 441]
类(Class)
ES2015 中的类(class)是在基于原型的面向对象模式上简单包装的语法糖。拥有一个 单一且方便的声明形式将更易于使用,并且 鼓励混合使用。类(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();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
Enhanced Object Literals
Object literals are extended to support setting the prototype at construction,
shorthand for foo: foo
assignments, defining methods and making super calls.
Together, these also bring object literals and class declarations closer
together, and let object-based design benefit from some of the same
conveniences.
var obj = {
// Sets the prototype. "__proto__" or '__proto__' would also work.
__proto__: theProtoObj,
// Computed property name does not set prototype or trigger early error for
// duplicate __proto__ properties.
['__proto__']: somethingElse,
// Shorthand for ‘handler: handler’
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names
[ "prop_" + (() => 42)() ]: 42
};
The proto
property requires native support, and was deprecated in previous ECMAScript versions. Most engines now support the property, but some do not. Also, note that only web browsers are required to implement it, as it's in Annex B. It is available in Node.
模板字符串
模板字符串为构造字符串提供了语法糖。这 类似于 Perl、Python 等语言中的字符串插值功能。另外, tag can be added to allow the string construction to be customized, avoiding injection attacks or constructing higher level data structures from string contents.
// 创建基本的字符串字面量(literal string)
`This is a pretty little template string.`
// 多行字符串
`In ES5 this is
not legal.`
// 插入变量绑定的值
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
// Unescaped template strings
String.raw`In ES5 "\n" is a line-feed.`
// Construct an HTTP request prefix is used to interpret the replacements and construction
GET`http://foo.org/bar?a=${a}&b=${b}
Content-Type: application/json
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}`(myOnReadyStateChangeHandler);
解构(Destructuring)
解构(Destructuring)允许基于模式匹配的方式进行赋值,这种模式匹配能够支持
数组(arrays)和对象(objects)。解构采取的是弱化故障的处理策略,类似于标准的对象
查找 foo["bar"]
,在未找到时返回值为 undefined
。
// list matching
var [a, ,b] = [1,2,3];
a === 1;
b === 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()
// Can be used in parameter position
function g({name: x}) {
console.log(x);
}
g({name: 5})
// Fail-soft destructuring
var [a] = [];
a === undefined;
// Fail-soft destructuring with defaults
var [a = 1] = [];
a === 1;
// Destructuring + defaults arguments
function r({x, y, w = 10, h = 10}) {
return x + y + w + h;
}
r({x:1, y:2}) === 23
Default + Rest + Spread
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.
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
Let + Const
限定在块级作用域的变量定义方式。let
是新的 var
。const
定义的变量只能被
赋值一次。静态限制可以防止在赋值前使用。
function f() {
{
let x;
{
// 因为此变量是块级作用域,因此是 ok 的
const x = "sneaky";
// 错误,定义的变量只能被赋值一次
x = "foo";
}
// 由于此变量是 `let` 定义的,因此是 ok 的
x = "bar";
// 错误,在同一块级作用域中已经被声明过了
let x = "inner";
}
}
Iterators + For..Of
Iterator 对象支持自定义迭代,就像 CLR 的 IEnumerable 或 Java 的
Iterable。利用 for..of
将 for..in
归纳为基于自定义迭代器的迭代。
不需要实现为一个数组,并且支持像
LINQ 一样的懒设计模式(lazy design patterns)。
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)就是基于这些假想类型的接口(使用 TypeScript 类型的语法仅用于阐述)实现的:
interface IteratorResult {
done: boolean;
value: any;
}
interface Iterator {
next(): IteratorResult;
}
interface Iterable {
[Symbol.iterator](): Iterator
}
如需使用 Iterators 功能,则必须引入 Babel 的 polyfill。
Generators
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).
Note: Can also be used to enable ‘await’-like async programming, see also ES7 await
proposal.
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):
interface Generator extends Iterator {
next(value?: any): IteratorResult;
throw(exception: any);
}
In order to use Generators you must include the Babel polyfill.
Comprehensions
在 Babel 6.0 中已删除
Unicode
持续完善对 Unicode 的全面支持,包括让字符串支持新的 unicode 文本(literal)
以及正则表达式(RegExp)新增的 u
模式能够支持 unicode 码位(code point),还有新的
API 用以处理 21bit 码位(code point)级别的字符串。这些新增的功能
让 JavaScript 可以构建全球化的应用程序。
// same as ES5.1
"𠮷".length == 2
// new RegExp behaviour, opt-in ‘u’
"𠮷".match(/./u)[0].length == 2
// new form
"\u{20BB7}" == "𠮷"
"𠮷" == "\uD842\uDFB7"
// new String ops
"𠮷".codePointAt(0) == 0x20BB7
// for-of iterates code points
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.
// lib/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
// app.js
import * as math from "lib/math";
console.log("2π = " + math.sum(math.pi, math.pi));
// otherApp.js
import {sum, pi} from "lib/math";
console.log("2π = " + sum(pi, pi));
Some additional features include export default
and 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";
console.log("e^π = " + exp(pi));