ECMAScript 2015 is an ECMAScript standard approved in June 2015.
ES2015 is an important update of the language and the first major update of the language since ES5 standardization in 2009. These functions are now being implemented in major JavaScript engines.
For the complete specification of ECMAScript 2015, please refer to the ES2015 standard. The following brief introduction is for reference only.
Arrow function and this
The arrow function is a function abbreviation using the => grammar. They are similar in grammar to the functions in C#, Java 8, and CaoffeeScript. They support expressions and body of statements. Unlike functions, arrow functions have the same scope as the code around this. If the arrow function is in 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 is a simple analogy to the prototype-based OO model. Having a convenient declarative form makes class schemas easier to use and encourages interoperability. Classes support prototype-based inheritance, super calls, instance and static methods, and constructors.
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 prototyping during construction, to provide abbreviations for foo: foo allocation, to define methods, and to make super calls. Together, they make object literal quantities and class declarations more compact and make object-based design more convenient.
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_ attribute requires native support and has been discarded in previous versions of ECMAScript. Most engines now support this attribute, but some do not.
Template string
Template strings provide syntax sugar for constructing strings. This is similar to the string interpolation function in Perl, Python, etc. Optionally, tags can be added to allow customized string construction to avoid injection attacks or to construct higher-level data structures from string content.
// Basic literal string creation `This is a pretty little template string.` // Multiline strings `In ES5 this is not legal.` // Interpolate variable bindings 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);
deconstruction
Deconstruction allows binding using pattern matching and supports matching arrays and objects. Similar to standard object lookup foo["bar"], the value undefined is generated when it is not found.
// 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 parameter + object expander + object collector
Default parameter values for the callee. Converts an array to a continuous parameter in a function call. Bind the following parameters to an array. Rest arguments more directly meet the need for common situations.
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-level scopes let and const
Block-wide binding constructs. let is a new var and const is a single task. Static restrictions prevent use before allocation.
function f() { { let x; { // this is ok since it's a block scoped name const x = "sneaky"; // error, was just defined with `const` above x = "foo"; } // this is ok since it was declared with `let` x = "bar"; // error, already declared above in this block let x = "inner"; } }
Iterator + For..Of
Iterator objects support custom iterations, such as CLR IEnumerable or Java Iterable. Use generic for..in to iterate for..of based on custom iterators. No need to implement arrays, LINQ and other inert design patterns are enabled.
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 (shown using only TypeScript type syntax):
interface IteratorResult { done: boolean; value: any; } interface Iterator { next(): IteratorResult; } interface Iterable { [Symbol.iterator](): Iterator }
Generators
The generator uses function * and simplified iterator yield. A function declared as function * returns a Generator instance. Generators are subtypes of iterators, including additional next and throw. These allow the value to flow back to the generator, so the yield expression returns a value (or throws it).
Note: It can also be used to enable'await'asynchronous programming, see also the 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 (shown using only TypeScript type syntax):
interface Generator extends Iterator { next(value?: any): IteratorResult; throw(exception: any); }
Unicode support
Non-destructive addition of complete Unicode is supported, including new Unicode literal form in strings, new RegExp mode for u-processing code points, and new API s for processing 21-bit code point-level strings. These new features support building global applications in JavaScript.
// same as ES5.1 "A kind of".length == 2 // new RegExp behaviour, opt-in 'u' "A kind of".match(/./u)[0].length == 2 // new form "\u{20BB7}" == "A kind of" == "\uD842\uDFB7" // new String ops "A kind of".codePointAt(0) == 0x20BB7 // for-of iterates code points for(var c of "A kind of") { console.log(c); }
Modular
Language-level support for modules defined by components. Coding patterns from popular JavaScript module loaders (AMD, Common JS). Runtime behavior defined by the default loader defined by the host. Implicit Asynchronous Model - Code will not execute until the requested module is 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 other functions 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));
Module Formatting
Babel can convert ES2015 modules into several different formats, including Common.js, AMD, System and UMD. You can even create your own.
Module Loading
Not ES2015
This is retained in the implementation definition in the ECMAScript 2015 specification. The final standard will be in the WHATWG Loader specification, but this is currently under way. The following is from the previous ES2015 draft.
Module loader support:
Dynamic Loading
Regional isolation
Global namespace isolation
Compile hook
Nested virtualization
Default module loaders can be configured, and new loaders can be constructed to call and load code in isolated or constrained contexts.
// Dynamic loading – 'System' is default loader 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
Need additional polyfill
Because Babel defaults to the common.js module, it does not contain the polyfill of the module loader API.
Using Module Loader
To use it, you need to tell Babel to use the system module formatter. Also be sure to check System.js
Map + Set + WeakMap + WeakSet
Efficient data structure of common algorithms. WeakMaps provides a leak-free object key table.
// 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
agent
Agents can create objects with all the behaviors available to host objects. It can be used for interception, object virtualization, logging/analysis, 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";
All run-time meta-operations have available methods:
var handler = { // target.prop get: ..., // target.prop = value set: ..., // 'prop' in target has: ..., // delete target.prop deleteProperty: ..., // target(...args) apply: ..., // new target(...args) construct: ..., // Object.getOwnPropertyDescriptor(target, 'prop') getOwnPropertyDescriptor: ..., // Object.defineProperty(target, 'prop', descriptor) defineProperty: ..., // Object.getPrototypeOf(target), Reflect.getPrototypeOf(target), // target.__proto__, object.isPrototypeOf(target), object instanceof target getPrototypeOf: ..., // Object.setPrototypeOf(target), Reflect.setPrototypeOf(target) setPrototypeOf: ..., // for (let i in target) {} enumerate: ..., // Object.keys(target) ownKeys: ..., // Object.preventExtensions(target) preventExtensions: ..., // Object.isExtensible(target) isExtensible :... }
Unsupported functionality
Due to ES5 limitations, agents cannot be converted or modified. See support in various JavaScript engines.
Symbols
Symbols enables access control for object state. Symbols allow attributes to be typed into string s (such as ES5) or symbol s. Symbols is a new primitive type. Optional parameters used in name debugging - but not part of Symbols. Symbols are unique (such as gensym), but not private, because they expose Object. getOwn Property Symbols through reflection.
(function() { // module scoped symbol var key = Symbol("key"); function MyClass(privateData) { this[key] = privateData; } MyClass.prototype = { doStuff: function() { ... this[key] ... } }; // Limited support from Babel, full support requires native implementation. typeof key === "symbol" })(); var c = new MyClass("hello") c["key"] === undefined
Limited support through polyfill
Limited support requires Babel polyfill. Due to language constraints, some functions cannot be converted or modified.
Subclasses can be built-in
In ES2015, built-in plug-ins like Array, Date and DOM ElementS can be inherited.
// User code of Array subclass class MyArray extends Array { constructor(...args) { super(...args); } } var arr = new MyArray(); arr[1] = 12; arr.length == 2
Partial support
The built-in subclass separability should be evaluated on a case-by-case basis, since HTMLElement classes can be subclassed, while many such as Date, Array and Error cannot be attributed to ES5 engine limitations.
Math + Number + String + Object Added APIs
Many new libraries have been added, including core math libraries, array conversion assistants, and Object.assign for replication.
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.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior [0, 0, 0].fill(7, 1) // [0,7,7] [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) })
Limited support from polyfill
Babel polyfill supports most of these API s. However, some functions are omitted for various reasons (for example, String.prototype.normalize requires a lot of extra code to support it).
Binary and octal
Two new digital text formats have been added for binary (b) and octal (o).
0b111110111 === 503 // true 0o767 === 503 // true
Support text only
babel can only transform 0o767 but not Number("0o767").
Promises
Promises is a library for asynchronous programming. Promise is the first type of representation of values that can be provided in the future. Promises are used in many existing JavaScript libraries.
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)]); })
Reflect API
Reflect API exposes runtime metaoperations of objects. This is actually a reversal of the Proxy API and allows calls to the same meta-operation as the proxy. Especially suitable for the realization of proxy.
var O = {a: 1}; Object.defineProperty(O, 'b', {value: 2}); O[Symbol('c')] = 3; Reflect.ownKeys(O); // ['a', 'b', Symbol(c)] function C(a, b){ this.c = a + b; } var instance = Reflect.construct(C, [20, 22]); instance.c; // 42
Tail Recursive Call
Make sure that tail placement calls do not increase the stack indefinitely. In the case of unbounded input, the recursive algorithm is safe.
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 ES2015 factorial(100000)
End, original English: https://github.com/lukehoban/....