ECMAScript 6
Dr. Axel Rauschmayer
2ality.com
2013-05-30
Fluent 2013, San Francisco
About me
Axel Rauschmayer:
Editor of JavaScript Weekly
Blogger at 2ality.com
Co-organizer of MunichJS (JavaScript user group)
I have written about ECMAScript 6 since early 2011.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 2 / 71
JavaScript: big and dangerous
Black rhinoceros: mammal with highest rate of mortal combat
(males: 50%).
JavaScript: Used for much more than it was originally created for.
Let’s make it better for those tasks. . .
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 3 / 71
ECMAScript 6
ECMAScript 6: next version of JavaScript (current: ECMAScript 5).
This talk:
Why (goals)?
How (design process)?
What (features)?
Warning
All information is preliminary, features can and will change.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 4 / 71
Background
Glossary
Important terms:
TC39 (Ecma Technical Committee 39): the committee evolving
JavaScript.
Members: companies (all major browser vendors etc.).
Meetings attended by employees and invited experts.
JavaScript: colloquially: the language; formally: one implementation
ECMAScript: the language standard
ECMAScript Harmony: improvements after ECMAScript 5
(ECMAScript 6 and 7)
ECMAScript.next: code name for upcoming version, subset of
Harmony
ECMAScript 6: the final name of ECMAScript.next (probably)
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 6 / 71
Goals for ECMAScript 6
One of several official goals [1]: make JavaScript better
for complex applications
for libraries (possibly including the DOM)
as a target of code generators
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 7 / 71
How ECMAScript features are designed
Avoid “design by committee”:
Design by “champions” (groups of 1–2 experts)
Feedback from TC39 and the web community
TC39 has final word on whether/when to include
Stages [2]:
Strawman proposal
TC39 is interested ∆ proposal
Field-testing via one or more implementations, refinements
TC39 accepts feature ∆ included in ECMAScript draft
Included in final spec ∆ Standard
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 8 / 71
Variables and scoping
Block-scoped variables
Function scope (var) Block scope (let, const)
function order(x, y) { function order(x, y) {
console.log(tmp); console.log(tmp);
// undefined // ReferenceError:
// tmp is not defined
if (x > y) { if (x > y) {
var tmp = x; let tmp = x;
x = y; x = y;
y = tmp; y = tmp;
} }
return [x, y]; return [x, y];
} }
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 10 / 71
Destructuring: objects
Extract data (more than one value!) via patterns:
let obj = { first: Jane , last: Doe };
let { first: f , last: l } = obj;
console.log(f + + l); // Jane Doe
Usage:
variable declarations
assignments
parameter definitions
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 11 / 71
Destructuring: arrays
let [x, y] = [ a , b ];
// x= a , y= b
let [x, y, ...rest] = [ a , b , c , d ];
// x= a , y= b , rest = [ c , d ]
[x,y] = [y,x]; // swap values
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 12 / 71
Destructuring: refutable by default
Refutable (default): exception if match isn’t exact.
{ a: x, b: y } = { a: 3 }; // fails
Irrefutable: always match.
{ a: x, ?b: y } = { a: 3 }; // x=3, y=undefined
Default value: use if no match or value is undefined
{ a: x, b: y=5 } = { a: 3 }; // x=3, y=5
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 13 / 71
Arrow functions
Arrow functions: less to type
Compare:
let squares = [1, 2, 3].map(function (x) {return x * x});
let squares = [1, 2, 3].map(x => x * x);
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 15 / 71
Arrow functions: lexical this, no more that=this
function UiComponent {
var that = this;
var button = document.getElementById( #myButton );
button.addEventListener( click , function () {
console.log( CLICK );
that.handleClick();
});
}
UiComponent.prototype.handleClick = function () { ... };
function UiComponent {
let button = document.getElementById( #myButton );
button.addEventListener( click , () => {
console.log( CLICK );
this.handleClick();
});
}
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 16 / 71
Arrow functions: versions
General form:
(arg1, arg2, ...) => expr
(arg1, arg2, ...) => { stmt1; stmt2; ... }
Shorter version – single parameter:
arg => expr
arg => { stmt1; stmt2; ... }
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 17 / 71
Parameter handling
Parameter handling 1: parameter default values
Use a default value if parameter is missing.
function func1(x, y=3) {
return [x,y];
}
Interaction:
> func1(1, 2)
[1, 2]
> func1(1)
[1, 3]
> func1()
[undefined, 3]
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 19 / 71
Parameter handling 2: rest parameters
Put trailing parameters in an array.
function func2(arg0, ...others) {
return others;
}
Interaction:
> func2(0, 1, 2, 3)
[1, 2, 3]
> func2(0)
[]
> func2()
[]
Eliminate the need for the special variable arguments.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 20 / 71
Spread operator (...)
Turn an array into function/method arguments:
> Math.max(7, 4, 11)
11
> Math.max(...[7, 4, 11])
11
The inverse of a rest parameter
Mostly replaces Function.prototype.apply()
Also works in constructors
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 21 / 71
Parameter handling 3: named parameters
Use destructuring for named parameters opt1 and opt2:
function func3(arg0, { opt1, opt2 }) {
return return [opt1, opt2];
}
// {opt1,opt2} is same as {opt1:opt1,opt2:opt2}
Interaction:
> func3(0, { opt1: a , opt2: b })
[ a , b ]
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 22 / 71
Object-orientation and modularity
Object literals
// ECMAScript 6
let obj = {
__proto__: someObject, // special property
myMethod(arg1, arg2) { // method definition
...
}
};
// ECMAScript 5
var obj = Object.create(someObject);
obj.myMethod = function (arg1, arg2) {
...
};
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 24 / 71
Object literals: property value shorthand
Shorthand: {x,y} is the same as { x: x, y: y }.
∆ Convenient for multiple return values.
function computePoint() {
let x = computeX();
let y = computeY();
return { x, y }; // shorthand
}
let {x,y} = computePoint(); // shorthand
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 25 / 71
Symbols
Inspired by Lisp, Smalltalk etc.
A new kind of primitive value:
> let sym = Symbol();
> typeof sym
symbol
Each symbol is unique.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 26 / 71
Symbols: enum-style values
let red = Symbol();
let green = Symbol();
let blue = Symbol();
function handleColor(color) {
switch(color) {
case red:
...
case green:
...
case blue:
...
}
}
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 27 / 71
Symbols: property keys
let specialMethod = Symbol();
let obj = {
// computed property key
[specialMethod]: function (arg) {
...
}
};
obj[specialMethod](123);
Shorter – method definition syntax:
let obj = {
[specialMethod](arg) {
...
}
};
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 28 / 71
Symbols: property keys
Advantage: No name clashes!
Configure objects for ECMAScript and frameworks
∆ publically known symbols
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 29 / 71
Classes
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return ( +this.x+ , +this.y+ ) ;
}
}
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return ( +this.x+ , +this.y+ ) ;
};
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 30 / 71
Classes: sub-type
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // same as super.constructor(x, y)
this.color = color;
}
toString() {
return this.color+ +super();
}
}
function ColorPoint(x, y, color) {
Point.call(this, x, y);
this.color = color;
}
ColorPoint.prototype = Object.create(Point.prototype);
ColorPoint.prototype.constructor = ColorPoint;
ColorPoint.prototype.toString = function () {
return this.color+ +Point.prototype.toString.call(this);
};
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 31 / 71
Static methods
class Point {
static zero() {
return new Point(0, 0);
}
constructor(x, y) {
this.x = x;
this.y = y;
}
}
let p = Point.zero();
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 32 / 71
Private properties
Hiding some properties from external access (object literals, classes):
Still under discussion.
Possibly: via a special kind of symbol.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 33 / 71
Modules: overview
// lib/math.js
let notExported = abc ;
export function square(x) {
return x * x;
}
export const MY_CONSTANT = 123;
// main.js
import {square} from lib/math ;
console.log(square(3));
Alternatively:
import lib/math as math;
console.log(math.square(3));
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 34 / 71
Modules: features
More features [3]:
Rename imports
Concatenation: put several modules in the same file
Module IDs are configurable (default: paths relative to importing file)
Programmatic (e.g. conditional) loading of modules via an API
Module loading is customizable:
Automatic linting (think: JSLint, JSHint)
Automatically translate files (CoffeeScript, TypeScript)
Use legacy modules (AMD, Node.js)
Syntax is still in flux!
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 35 / 71
Template strings
Template strings: string interpolation
Invocation:
templateHandler Hello ${first} ${last}!
Syntactic sugar for:
templateHandler([ Hello , , ! ], first, last)
Two kinds of tokens:
Literal sections (static): Hello
Substitutions (dynamic): first
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 37 / 71
Template strings: raw strings
Multiple lines, no escaping:
var str = raw This is a text
with multiple lines.
Escapes are not interpreted,
\n is not a newline. ;
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 38 / 71
Template strings: other use cases
Regular expressions (XRegExp: multi-line, ignoring whitespace)
Query languages
Text localization
Templating
etc.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 39 / 71
Standard library
Maps
Data structure mapping from arbitrary values to arbitrary values
(objects: keys must be strings).
let map = new Map();
let obj = {};
map.set(obj, 123);
console.log(map.get(obj)); // 123
console.log(map.has(obj)); // true
map.delete(obj);
console.log(map.has(obj)); // false
Also: iteration (over keys, values, entries) and more.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 41 / 71
Sets
A collection of values without duplicates.
let set1 = new Set();
set1.add( hello );
console.log(set1.has( hello )); // true
console.log(set1.has( world )); // false
let set2 = new Set([3,2,1,3,2,3]);
console.log(set2.values()); // 1,2,3
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 42 / 71
Object.assign
Merge one object into another one.
class Point {
constructor(x, y) {
Object.assign(this, { x, y });
}
}
Similar to Underscore.js _.extend().
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 43 / 71
Various other additions to the standard library
> abc .repeat(3)
abcabcabc
> abc .startsWith( ab )
true
> abc .endsWith( bc )
true
And more!
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 44 / 71
Loops and iteration
Iterables and iterators
Iterable: Iterator:
traversable data structure pointer for traversing iterable
... returns next()
[iterate]()
Examples of iterables:
Arrays
Results produced by tool functions and methods
(keys(), values(), entries()).
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 46 / 71
Iterators
import {iterate} from @iter ; // symbol
function iterArray(arr) {
let i = 0;
return { // both iterable and iterator
[iterate]() { // iterable
return this; // iterator
},
next() { // iterator
if (i < arr.length) {
return { value: arr[i++] };
} else {
return { done: true };
} } } }
for (let elem of iterArray([ a , b ])) {
console.log(elem);
}
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 47 / 71
for-of: a better loop
Current looping constructs:
for-in:
Basically useless for arrays
Quirky for objects
Array.prototype.forEach():
doesn’t work with iterables
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 48 / 71
for-of loop: iterables
Looping over iterables (incl. arrays).
let arr = [ hello , world ];
for (let elem of arr) {
console.log(elem);
}
Output – elements, not indices:
hello
world
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 49 / 71
for-of loop: objects
let obj = { first: Jane , last: Doe };
Iterate over properties:
import {entries} from @iter ; // returns an iterable
for (let [key, value] of entries(obj)) {
console.log(key + = + value);
}
Iterate over property names:
import {keys} from @iter ; // returns an iterable
for (let name of keys(obj)) {
console.log(name);
}
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 50 / 71
Generators
Generators: suspend and resume
function* generatorFunction() {
... a function
yield x;
... Shallow coroutines [4]: only
} function body is suspended.
Uses: iterators, simpler
returns
asynchronous programming.
generatorObject
next()
yield
next()
yield
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 52 / 71
Generators: example
Suspend via yield (“resumable return”):
function* generatorFunction() {
yield 0;
yield 1;
yield 2;
}
Start and resume via next():
let genObj = generatorFunction();
console.log(genObj.next()); // 0
console.log(genObj.next()); // 1
console.log(genObj.next()); // 2
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 53 / 71
Generators: implementing an iterator
An iterator for nested arrays:
function* iterTree(tree) {
if (Array.isArray(tree)) {
// inner node
for(let i=0; i < tree.length; i++) {
yield* iterTree(tree[i]); // recursion
}
} else {
// leaf
yield tree;
}
}
Difficult to write without recursion.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 54 / 71
Generators: asynchronous programming
Using the task.js library:
spawn(function* () {
try {
var [foo, bar] = yield join(
read("foo.json") , read("bar.json")
).timeout(1000);
render(foo);
render(bar);
} catch (e) {
console.log("read failed: " + e);
}
});
Wait for asynchronous calls via yield (internally based on promises).
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 55 / 71
Comprehensions
Array comprehensions produce an array:
let numbers = [1,2,3];
let squares = [for (x of numbers) x*x];
Generator comprehensions produce a generator object (an iterator):
let squares = (for (x of numbers) x*x);
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 56 / 71
Conclusion
Time table
ECMAScript specification:
November 2013: final review of draft
July 2014: editorially complete
December 2014: Ecma approval
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 58 / 71
Using ECMAScript 6 today
First features are already in engines [5]
Traceur by Google: compiles ECMAScript 6 to ECMAScript 5.
dynamically (on the fly)
statically (e.g. via tools)
TypeScript by Microsoft:
ECMAScript 6 + optional static typing (at development time)
compiles to ECMAScript 5
es6-shim by Paul Miller: features of the ES6 standard library,
backported to ES5.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 59 / 71
Thank you!
Annex
References
1 ECMAScript Harmony wiki
2 “The Harmony Process” by David Herman
3 “ES6 Modules” by Yehuda Katz
4 “Why coroutines won’t work on the web” by David Herman
5 “ECMAScript 6 compatibility table” by kangax [features already in
JavaScript engines]
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 62 / 71
Resources
ECMAScript 6 specification drafts by Allen Wirfs-Brock
ECMAScript mailing list: es-discuss
TC39 meeting notes by Rick Waldron
“A guide to 2ality’s posts on ECMAScript 6” by Axel Rauschmayer
Continuum, an ECMAScript 6 virtual machine written in
ECMAScript 3.
(Links are embedded in this slide.)
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 63 / 71
Bonus: proxies
Proxies
Observe operations applied to object proxy, via handler h:
let target = {};
let proxy = Proxy(target, h);
Each of the following operations triggers a method invocation on h:
proxy[ foo ] æ h.get(target, foo , p)
proxy[ foo ] = 123 æ h.set(target, foo , 123, p)
foo in proxy æ h.has(target, foo )
for (key in proxy) {...} æ h.enumerate(target)
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 65 / 71
Proxies in the prototype chain
let child = Object.create(proxy);
Operations on child can still trigger handler invocations
(if the search for properties reaches proxy):
child[ foo ] æ h.get(target, foo , ch)
child[ foo ] = 123 æ h.set(target, foo , 123, ch)
foo in child æ h.has(target, foo )
for (key in child) {...} æ h.enumerate(target)
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 66 / 71
Proxy: example
let handler = {
get(target, name, receiver) {
return (...args) => {
console.log( Missing method +name
+ , arguments: +args);
}
}
};
let proxy = Proxy({}, handler);
Using the handler:
> let obj = Object.create(proxy);
> obj.foo(1, 2)
Missing method foo, arguments: 1, 2
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 67 / 71
Use cases for proxies
Typical meta-programming tasks:
Sending all method invocations to a remote object
Implementing data access objects for a database
Data binding
Logging
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 68 / 71
More bonus slides
Template strings: regular expressions
ECMAScript 5 (XRegExp library):
var str = /2012/10/Page.html ;
var parts = str.match(XRegExp(
^ # match at start of string only \n +
/ (?<year> [^/]+ ) # capture top dir as year \n +
/ (?<month> [^/]+ ) # capture subdir as month \n +
/ (?<title> [^/]+ ) # file name base \n +
\\.html? # file name extension: .htm or .html \n +
$ # end of string ,
x
));
console.log(parts.year); // 2012
XRegExp features: named groups, ignored whitespace, comments.
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 70 / 71
Template strings: regular expressions
ECMAScript 6:
let str = /2012/10/Page.html ;
let parts = str.match(XRegExp.rx
^ # match at start of string only
/ (?<year> [^/]+ ) # capture top dir as year
/ (?<month> [^/]+ ) # capture subdir as month
/ (?<title> [^/]+ ) # file name base
\.html? # file name extension: .htm or .html
$ # end of string
);
Advantages:
Raw characters: no need to escape backslash and quote
Multi-line: no need to concatenate strings with newlines at the end
Dr. Axel Rauschmayer (2ality.com) ECMAScript 6 2013-05-30 71 / 71