//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));
//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) )
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 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 } }
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)
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() } }
class Rectangle extends Shape { ... static defaultRectangle() { return new Rectangle('default', 0, 0, 100, 100) } } var defRectangle = Rectangle.defaultRectangle()
class Rectangle { constructor(width, height){ this._width = width; this._height = height; } set width(width) { this._width = width; } get width() { return this._width; } }
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 ]
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 ]
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); }
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); }
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 }
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)
// 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" })
class Clz { * bar () { … } } let Obj = { * foo () { … } }
集合對象, 容許你存儲任意類型的惟一值(不能重複),不管它是原始值或者是對象引用es6
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)
簡單的鍵/值映射。其中鍵和值能夠是任意值(對象或者原始值)。app
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); } }
鍵/值對的集合,且其中的鍵是弱引用的。其鍵只能是對象,而值則能夠是任意的。async
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
// 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
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;
[ 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
let depth = 1; //" " " ".repeat(4 * depth); //"foofoofoo" "foo".repeat(3);
"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.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.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;
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
感受和parseInt沒區別啊oop
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
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
Promisesfetch
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); }); });
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-Programmingui
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"
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" ]
// 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", "ä" ]
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"
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 €"
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.orgthis