modules 模块
Value Export/Import
//lib/math.js
export function sum(x, y){return x + y}
export var pi = 3.141593
//someApp.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) );
//es5
LibMath = {};
LibMath.sum = function(x, y){ return x + y};
LibMath.pi = 3.141593
var math = LibMath;
console.log('2π= ' + math.sum(math.pi, math.pi));
var sum = LibMath.sum, pi = LibMath.pi;
console.log('2π= ' + sum(pi,pi));
Default & Wildcard 默认值和通配符
//lib/math.js
export * from 'lib/math'
export var e = 2.1731323232
export default (x) => Math.exp(x)
//some App.js
import exp, {pi,e} from 'lib/math'
console.log('e^{π} = ' + exp(pi) )
Classes 类
Class Definition 类的定义
class Shape {
constructor(id, x, y){
this.id = id
this.move(x, y)
}
move (x, y) {
this.x = x
this.y = y
}
}
//es5
var Shape = function(id, x, y){
this.id = id;
this.move(x, y);
}
Shape.prototype.move = function(x, y){
this.x = x;
this.y = y;
}
Class Inheritance 类继承
class Rectangle extends Shape {
constructor(id, x, y, width, height){
super(id, x, y)
this.width = width
this.height = height
}
}
class Circle extends Shape {
constructor(id, x, y, radius) {
super(id, x, y)
this.radius = radius
}
}
Class Inheritance, From Expressions表达式方式的类继承
var aggregation = (baseClass, ...mixins) => {
let base = class _Combined extends baseClass {
constructor (...args) {
super(...args)
mixins.forEach((mixin) => {
mixin.prototype.initializer.call(this)
})
}
}
let copyProps = (target, source) => {
Object.getOwnPropertyNames(source)
.concat(Object.getOwnPropertySymbols(source))
.forEach((prop) => {
if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
return
Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
})
}
mixins.forEach((mixin) => {
copyProps(base.prototype, mixin.prototype)
copyProps(base, mixin)
})
return base
}
class Colored {
initializer () { this._color = "white" }
get color () { return this._color }
set color (v) { this._color = v }
}
class ZCoord {
initializer () { this._z = 0 }
get z () { return this._z }
set z (v) { this._z = v }
}
class Shape {
constructor (x, y) { this._x = x; this._y = y }
get x () { return this._x }
set x (v) { this._x = v }
get y () { return this._y }
set y (v) { this._y = v }
}
class Rectangle extends aggregation(Shape, Colored, ZCoord) {}
var rect = new Rectangle(7, 42)
rect.z = 1000
rect.color = "red"
console.log(rect.x, rect.y, rect.z, rect.color)
Base Class Access基类访问
class Shape {
…
toString () {
return `Shape(${this.id})`
}
}
class Rectangle extends Shape {
constructor (id, x, y, width, height) {
super(id, x, y)
…
}
toString () {
return "Rectangle > " + super.toString()
}
}
class Circle extends Shape {
constructor (id, x, y, radius) {
super(id, x, y)
…
}
toString () {
return "Circle > " + super.toString()
}
}
Static Members
class Rectangle extends Shape {
...
static defaultRectangle() {
return new Rectangle('default', 0, 0, 100, 100)
}
}
var defRectangle = Rectangle.defaultRectangle()
Getter/Setter
class Rectangle {
constructor(width, height){
this._width = width;
this._height = height;
}
set width(width) { this._width = width; }
get width() { return this._width; }
}
Symbol Type
Symbol Type
Symbol("foo") !== Symbol("foo")
const foo = Symbol()
const bar = Symbol()
typeof foo === "symbol"
typeof bar === "symbol"
let obj = {}
obj[foo] = "foo"
obj[bar] = "bar"
JSON.stringify(obj) // {}
Object.keys(obj) // []
Object.getOwnPropertyNames(obj) // []
Object.getOwnPropertySymbols(obj) // [ foo, bar ]
Global Symbols
Symbol.for("app.foo") === Symbol.for("app.foo")
const foo = Symbol.for("app.foo")
const bar = Symbol.for("app.bar")
Symbol.keyFor(foo) === "app.foo"
Symbol.keyFor(bar) === "app.bar"
typeof foo === "symbol"
typeof bar === "symbol"
let obj = {}
obj[foo] = "foo"
obj[bar] = "bar"
JSON.stringify(obj) // {}
Object.keys(obj) // []
Object.getOwnPropertyNames(obj) // []
Object.getOwnPropertySymbols(obj) // [ foo, bar ]
Iterators迭代器
Iterator & For-Of Operator
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1
return {
next () {
[ pre, cur ] = [ cur, pre + cur ]
return { done: false, value: cur }
}
}
}
}
for (let n of fibonacci) {
if (n > 1000)
break
console.log(n)
}
//es5
var fibonacci = {
next: (function () {
var pre = 0, cur = 1;
return function () {
tmp = pre;
pre = cur;
cur += tmp;
return cur;
};
})()
};
var n;
for (;;) {
n = fibonacci.next();
if (n > 1000)
break;
console.log(n);
}
Generators 生成器
Generator Function, Iterator Protocol
let fibonacci = {
*[Symbol.iterator]() {
let pre = 0, cur = 1
for (;;) {
[ pre, cur ] = [ cur, pre + cur ]
yield cur
}
}
}
for (let n of fibonacci) {
if (n > 1000)
break
console.log(n)
}
//es5
var fibonacci = {
next: (function () {
var pre = 0, cur = 1;
return function () {
tmp = pre;
pre = cur;
cur += tmp;
return cur;
};
})()
};
var n;
for (;;) {
n = fibonacci.next();
if (n > 1000)
break;
console.log(n);
}
Generator Function, Direct Use
function* range (start, end, step) {
while (start < end) {
yield start
start += step
}
}
for (let i of range(0, 10, 2)) {
console.log(i) // 0, 2, 4, 6, 8
}
//es5
function range (start, end, step) {
var list = [];
while (start < end) {
list.push(start);
start += step;
}
return list;
}
var r = range(0, 10, 2);
for (var i = 0; i < r.length; i++) {
console.log(r[i]); // 0, 2, 4, 6, 8
}
Generator Matching
let fibonacci = function* (numbers) {
let pre = 0, cur = 1
while (numbers-- > 0) {
[ pre, cur ] = [ cur, pre + cur ]
yield cur
}
}
for (let n of fibonacci(1000))
console.log(n)
let numbers = [ ...fibonacci(1000) ]
let [ n1, n2, n3, ...others ] = fibonacci(1000)
Generator Control-Flow
// generic asynchronous control-flow driver
function async (proc, ...params) {
var iterator = proc(...params)
return new Promise((resolve, reject) => {
let loop = (value) => {
let result
try {
result = iterator.next(value)
}
catch (err) {
reject(err)
}
if (result.done)
resolve(result.value)
else if ( typeof result.value === "object"
&& typeof result.value.then === "function")
result.value.then((value) => {
loop(value)
}, (err) => {
reject(err)
})
else
loop(result.value)
}
loop()
})
}
// application-specific asynchronous builder
function makeAsync (text, after) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(text), after)
})
}
// application-specific asynchronous procedure
async(function* (greeting) {
let foo = yield makeAsync("foo", 300)
let bar = yield makeAsync("bar", 200)
let baz = yield makeAsync("baz", 100)
return `${greeting} ${foo} ${bar} ${baz}`
}, "Hello").then((msg) => {
console.log("RESULT:", msg) // "Hello foo bar baz"
})
Generator Methods
class Clz {
* bar () {
…
}
}
let Obj = {
* foo () {
…
}
}
Map/Set & WeakMap/WeakSet
Set Data-Structure
集合对象, 允许你存储任意类型的唯一值(不能重复),无论它是原始值或者是对象引用
let s = new Set()
s.add("hello").add("goodbye").add("hello")
s.size === 2
s.has("hello") === true
for (let key of s.values()) // insertion order
console.log(key)
Map Data-Structure Map
简单的键/值映射。其中键和值可以是任意值(对象或者原始值)。
let m = new Map()
let s = Symbol()
m.set("hello", 42)
m.set(s, 34)
m.get(s) === 34
m.size === 2
for (let [ key, val ] of m.entries())
console.log(key + " = " + val)
//ES5
var m = {};
// no equivalent in ES5
m["hello"] = 42;
// no equivalent in ES5
// no equivalent in ES5
Object.keys(m).length === 2;
for (key in m) {
if (m.hasOwnProperty(key)) {
var val = m[key];
console.log(key + " = " + val);
}
}
Weak-Link Data-Structures
键/值对的集合,且其中的键是弱引用的。其键只能是对象,而值则可以是任意的。
let isMarked = new WeakSet()
let attachedData = new WeakMap()
export class Node {
constructor (id) { this.id = id }
mark () { isMarked.add(this) }
unmark () { isMarked.delete(this) }
marked () { return isMarked.has(this) }
set data (data) { attachedData.set(this, data) }
get data () { return attachedData.get(this) }
}
let foo = new Node("foo")
JSON.stringify(foo) === '{"id":"foo"}'
foo.mark()
foo.data = "bar"
foo.data === "bar"
JSON.stringify(foo) === '{"id":"foo"}'
isMarked.has(foo) === true
attachedData.has(foo) === true
foo = null /* remove only reference to foo */
attachedData.has(foo) === false
isMarked.has(foo) === false
Typed Arrays
// ES6 class equivalent to the following C structure:
// struct Example { unsigned long id; char username[16]; float amountDue }
class Example {
constructor (buffer = new ArrayBuffer(24)) {
this._buffer = buffer
}
set buffer (buffer) {
this._buffer = buffer
this._id = new Uint32Array (this._buffer, 0, 1)
this._username = new Uint8Array (this._buffer, 4, 16)
this._amountDue = new Float32Array(this._buffer, 20, 1)
}
get buffer () { return this._buffer }
set id (v) { this._id[0] = v }
get id () { return this._id[0] }
set username (v) { this._username[0] = v }
get username () { return this._username[0] }
set amountDue (v) { this._amountDue[0] = v }
get amountDue () { return this._amountDue[0] }
}
let example = new Example()
example.id = 7
example.username = "John Doe"
example.amountDue = 42.0
New Built-In Methods 新的内置方法
Object Property Assignment
var dst = { quux: 0 }
var src1 = { foo: 1, bar: 2 }
var src2 = { foo: 3, baz: 4 }
Object.assign(dst, src1, src2)
dst.quux === 0
dst.foo === 3
dst.bar === 2
dst.baz === 4
//es5
var dst = { quux: 0 };
var src1 = { foo: 1, bar: 2 };
var src2 = { foo: 3, baz: 4 };
Object.keys(src1).forEach(function(k) {
dst[k] = src1[k];
});
Object.keys(src2).forEach(function(k) {
dst[k] = src2[k];
});
dst.quux === 0;
dst.foo === 3;
dst.bar === 2;
dst.baz === 4;
Array Element Finding
[ 1, 3, 4, 2 ].find(x => x > 3) // 4
[ 1, 3, 4, 2 ].findIndex(x => x > 3) // 2
//es5
[ 1, 3, 4, 2 ].filter(function (x) { return x > 3; })[0]; // 4
// no equivalent in ES5
String Repeating
let depth = 1;
//" "
" ".repeat(4 * depth);
//"foofoofoo"
"foo".repeat(3);
String Searching
"hello".startsWith("ello", 1) // true
"hello".endsWith("hell", 4) // true
"hello".includes("ell") // true
"hello".includes("ell", 1) // true
"hello".includes("ell", 2) // false
//es5
"hello".indexOf("ello") === 1; // true
"hello".indexOf("hell") === (4 - "hell".length); // true
"hello".indexOf("ell") !== -1; // true
"hello".indexOf("ell", 1) !== -1; // true
"hello".indexOf("ell", 2) !== -1; // false
Number Type Checking
Number.isNaN(42) === false
Number.isNaN(NaN) === true
Number.isFinite(Infinity) === false
Number.isFinite(-Infinity) === false
Number.isFinite(NaN) === false
Number.isFinite(123) === true
//es5
var isNaN = function (n) {
return n !== n;
};
var isFinite = function (v) {
return (typeof v === "number" && !isNaN(v) && v !== Infinity && v !== -Infinity);
};
isNaN(42) === false;
isNaN(NaN) === true;
isFinite(Infinity) === false;
isFinite(-Infinity) === false;
isFinite(NaN) === false;
isFinite(123) === true;
Number Safety Checking
Number.isSafeInteger(42) === true
Number.isSafeInteger(9007199254740992) === false
//es5
function isSafeInteger (n) {
return (
typeof n === 'number'
&& Math.round(n) === n
&& -(Math.pow(2, 53) - 1) <= n
&& n <= (Math.pow(2, 53) - 1)
);
}
isSafeInteger(42) === true;
isSafeInteger(9007199254740992) === false;
Number Comparison
console.log(0.1 + 0.2 === 0.3) // false
console.log(Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON) // true
//es5
console.log(0.1 + 0.2 === 0.3); // false
console.log(Math.abs((0.1 + 0.2) - 0.3) < 2.220446049250313e-16); // true
Number Truncation
感觉和parseInt没区别啊
console.log(Math.trunc(42.7)) // 42
console.log(Math.trunc( 0.1)) // 0
console.log(Math.trunc(-0.1)) // -0
//es5
function mathTrunc (x) {
return (x < 0 ? Math.ceil(x) : Math.floor(x));
}
console.log(mathTrunc(42.7)) // 42
console.log(mathTrunc( 0.1)) // 0
console.log(mathTrunc(-0.1)) // -0
Number Sign Determination
console.log(Math.sign(7)) // 1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-0)) // -0
console.log(Math.sign(-7)) // -1
console.log(Math.sign(NaN)) // NaN
//es5
function mathSign (x) {
return ((x === 0 || isNaN(x)) ? x : (x > 0 ? 1 : -1));
}
console.log(mathSign(7)) // 1
console.log(mathSign(0)) // 0
console.log(mathSign(-0)) // -0
console.log(mathSign(-7)) // -1
console.log(mathSign(NaN)) // NaN
Promises
Promise Usage
function msgAfterTimeout (msg, who, timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(`${msg} Hello ${who}!`), timeout)
})
}
msgAfterTimeout("", "Foo", 100).then((msg) =>
msgAfterTimeout(msg, "Bar", 200)
).then((msg) => {
console.log(`done after 300ms:${msg}`)
})
//ES5
function msgAfterTimeout (msg, who, timeout, onDone) {
setTimeout(function () {
onDone(msg + " Hello " + who + "!");
}, timeout);
}
msgAfterTimeout("", "Foo", 100, function (msg) {
msgAfterTimeout(msg, "Bar", 200, function (msg) {
console.log("done after 300ms:" + msg);
});
});
Promise Combination
function fetchAsync (url, timeout, onData, onError) {
…
}
let fetchPromised = (url, timeout) => {
return new Promise((resolve, reject) => {
fetchAsync(url, timeout, resolve, reject)
})
}
Promise.all([
fetchPromised("http://backend/foo.txt", 500),
fetchPromised("http://backend/bar.txt", 500),
fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
let [ foo, bar, baz ] = data
console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
console.log(`error: ${err}`)
})
//ES5
function fetchAsync (url, timeout, onData, onError) {
…
}
function fetchAll (request, onData, onError) {
var result = [], results = 0;
for (var i = 0; i < request.length; i++) {
result[i] = null;
(function (i) {
fetchAsync(request[i].url, request[i].timeout, function (data) {
result[i] = data;
if (++results === request.length)
onData(result);
}, onError);
})(i);
}
}
fetchAll([
{ url: "http://backend/foo.txt", timeout: 500 },
{ url: "http://backend/bar.txt", timeout: 500 },
{ url: "http://backend/baz.txt", timeout: 500 }
], function (data) {
var foo = data[0], bar = data[1], baz = data[2];
console.log("success: foo=" + foo + " bar=" + bar + " baz=" + baz);
}, function (err) {
console.log("error: " + err);
});
Meta-Programming
Proxying
let target = {
foo: "Welcome, foo"
}
let proxy = new Proxy(target, {
get (receiver, name) {
return name in receiver ? receiver[name] : `Hello, ${name}`
}
})
proxy.foo === "Welcome, foo"
proxy.world === "Hello, world"
Reflection
let obj = { a: 1 }
Object.defineProperty(obj, "b", { value: 2 })
obj[Symbol("c")] = 3
Reflect.ownKeys(obj) // [ "a", "b", Symbol(c) ]
//ES5
var obj = { a: 1 };
Object.defineProperty(obj, "b", { value: 2 });
// no equivalent in ES5
Object.getOwnPropertyNames(obj); // [ "a", "b" ]
Internationalization & Localization
Collation
// in German, "ä" sorts with "a"
// in Swedish, "ä" sorts after "z"
var list = [ "ä", "a", "z" ]
var l10nDE = new Intl.Collator("de")
var l10nSV = new Intl.Collator("sv")
l10nDE.compare("ä", "z") === -1
l10nSV.compare("ä", "z") === +1
console.log(list.sort(l10nDE.compare)) // [ "a", "ä", "z" ]
console.log(list.sort(l10nSV.compare)) // [ "a", "z", "ä" ]
Number Formatting
var l10nEN = new Intl.NumberFormat("en-US")
var l10nDE = new Intl.NumberFormat("de-DE")
l10nEN.format(1234567.89) === "1,234,567.89"
l10nDE.format(1234567.89) === "1.234.567,89"
Currency Formatting
var l10nUSD = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
var l10nGBP = new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP" })
var l10nEUR = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" })
l10nUSD.format(100200300.40) === "$100,200,300.40"
l10nGBP.format(100200300.40) === "£100,200,300.40"
l10nEUR.format(100200300.40) === "100.200.300,40 €"
Date/Time Formatting
var l10nEN = new Intl.DateTimeFormat("en-US")
var l10nDE = new Intl.DateTimeFormat("de-DE")
l10nEN.format(new Date("2015-01-02")) === "1/2/2015"
l10nDE.format(new Date("2015-01-02")) === "2.1.2015"
FROM:
http://es6-features.org
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。