ECMAScript 6
Luke Hoban
git.io/es6features
ECMAScript History
1997
ECMAScript 1
1998
2009
ECMAScript 2
ECMAScript 5
2005 - 2007
1999
2014
ECMAScript 4 - Abandoned
ECMAScript 3
ECMAScript 6?
2014
1998
1997
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2015
ECMAScript 6
• ES6
•
•
•
More significant changes than ES5
Much more new syntax
Very, very high back compat
• Spec drafts
•
•
•
•
•
•
•
Spec drafts
~ Monthly updates
Currently at Rev 25
Spec ‘feature complete’
‘Final’ spec target 7/2014
ECMA ratification target 12/2014
Implementation progress: http://kangax.github.io/es5-compat-table/es6/
ES6 for Developers
(the sugar)
4
arrows
// Expression bodies
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
•
•
•
•
Function shorthand with =>
Syntactically similar to C#, Java 8,
CoffeeScript
Support for expression and statement
bodies
Goal: Shorthand for common usage of
functions as callbacks
// 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));
}
}
classes
•
•
•
•
Simple classes as sugar
Compiles to prototype-based OO
pattern
Formalizes common JS OO pattern into
syntax
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
Goal: Declarative classes covering
common case
}
update(camera) {
//...
super.update();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
enhanced object literals
•
•
Richer object literals
Covers common scenarios like:
•
•
•
setting prototype at construction
defining methods
accessing super from method
var obj = {
// __proto__
__proto__: theProtoObj,
// Shorthand for ‘handler: handler’
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString()
}
};
template strings
•
•
Syntactic sugar for string construction
Similar to string interpolation in Perl,
Python
•
Goal: Make it easier to construct strings
with less risk of injection attacks
// Basic literal string creation
`In JavaScript '\n' is a line-feed.`
// Multiline strings
`In JavaScript this is
not legal.`
// Construct a DOM query
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
// 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
•
•
Binding via pattern matching
Support for matching arrays, objects
// list matching
var [a, , b] = [1,2,3];
// object matching
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode()
// Can be used in parameter position
function g({name: x}) {
console.log(x);
}
g({name: 5})
default + rest + spread
•
•
•
•
Callee-evaluated default parameter
values
Turn an array into consecutive
arguments in a function call
Bind trailing parameters to an array
Goal: Write less code, replace
‘arguments’
function f(x, y=12) {
// y is 12 if not passed
return x + y;
}
f(3)
function f(x, ...y) {
// y is an Array
return x * y.length;
}
f(3, "hello", true)
function f(x, y, z) {
return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3])
ES6 for Library Builders
(the capabilities)
11
map + set + weakmap
•
•
•
Efficient Map and Set data structures
WeakMap provides leak-free objectkey’d side tables
Goal: Enable libraries to provide new
experiences
// 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();
m.set(s, { extra: 42 });
m.size === undefined
proxies
•
•
•
•
•
Enable creation of objects with full
range of behaviors available to host
object
Support interception, object
virtualization, logging/profiling, etc.
Continue the direction set by Object.* in
ES5
Goal: Enable libraries to provide new
experiences
Semantics: Proxy semantics restricted to
“proxy” objects, not general
interception
var handler =
{
getOwnPropertyDescriptor: ...,
getOwnPropertyNames: ...,
defineProperty: ...,
deleteProperty: ...,
get: ...,
set: ...,
// …
}
var obj = {x: 1};
// Create a proxy wrapping an object
var proxy = Proxy(obj, handler);
// Invokes trap on handler
proxy.x = 3;
symbols
•
•
•
•
•
Allow properties to be keyed by either
string (as in ES5) or Symbols
Symbols are a new primitive type
Optional ‘name’ parameter used in
debugging
Goal: Enable granular access control to
per-instance properties
Note: Originally two kinds ‘private’ and
‘unique’.
•
•
Private are not exposed to reflection APIs.
These were postponed out of ES6 due to
complexities rationalizing with proxies and
other reflection mechanisms.
Unique are exposed to reflection like normal
properties. There continues to be discussion
about whether these are worth it given the
limitied benefit over “_key”.
(function() {
// module scoped symbol
var key = Symbol("key");
function MyClass(privateData) {
this[key] = privateData;
}
MyClass.prototype = {
doStuff: function() {
... this[key] ...
}
};
})();
var c = new MyClass("hello")
c["key"] === undefined
subclassable builtins
•
Construction for Ctor now uses twophases (both virtually dispatched):
•
•
•
•
•
•
Call Ctor[@@create] to allocate the object,
installing any special behavior
Invoke constructor on new instance to initialize
The known @@create symbol is
available via Symbol.create
Built-ins now expose their @@create
explicitly
Goal: Enable subclassing built-ins like
Array, Date and DOM.
Note: Web components can leverage
DOM subclassability.
// Psuedo-code of Array
class Array {
constructor(...args) { /* ... */ }
static [Symbol.create]() {
// Install special [[DefineOwnProperty]]
// to magically update 'length'
}
}
// User code of Array subclass
class MyArray extends Array {
constructor(...args) { super(...args); }
}
// Two-phase 'new':
// 1) Call @@create to allocate object
// 2) Invoke constructor on new instance
var arr = new MyArray();
arr[1] = 12;
arr.length == 2
tail calls
•
•
•
Calls in tail-position are guaranteed to
not grow the stack unboundedly.
Makes recursive algorithms safe in the
face of unbounded inputs.
Provides a better compilation target for
languages that depend on tail call
optimization
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 eS6
factorial(100000)
ES6 for Scalable Applications
(the meat)
17
let + const
•
Block-scoped binding
•
•
‘let’ is the new ‘var’
‘const’ is single-assignment
•
Goal: Address existing confusion
around scoping, align with expectation
from other C-style languages
Goal: ‘const’ offers optimization
opportunities
•
•
Semantics: No use before definition
function f() {
{
let x;
{
// okay, block scoped name
const x = "sneaky";
// error, const
x = "foo";
}
// error, already declared in block
let x = "inner";
}
}
iterators + for..of
•
•
•
•
Iterator objects enable custom iteration like CLR
IEnumerable or Java Iteratable
Generalize for-in to custom iterator-based iteration
with for-of
Don’t require realizing an array
Goal: Open up new kinds of iteration, including
databases (LINQ)
interface IteratorResult {
done: boolean;
value: any;
}
interface Iterator {
next(): IteratorResult;
}
interface Iterable {
[Symbol.iterator](): Iterator
}
var fibonacci = {
[Symbol.iterator]() {
var pre = 0, cur = 1;
return {
next() {
var temp = pre; pre = cur; cur += temp;
return { done: false, value: cur }
}
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
print(n);
}
generators
•
•
•
Simplify iterator-authoring using ‘function*’
and ‘yield’
A function declared as function* returns a
Generator instance
Generators are subtypes of Iterators
•
•
Notably enabling values to flow back into the generator
So ‘yield’ is an expression form which returns a value (or
throws)
interface Generator extends Iterator {
next(value?: any): IteratorResult;
throw(exception: any);
}
•
Goal: Open up new kinds of iteration,
including databases (LINQ)
•
Note: Enables ‘await’-like async programming
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;
print(n);
}
comprehensions
•
•
Sugar over simple iterator composition
Option to realize results as array or generator
•
Goal: Compact queries over in memory data
// Array comprehensions
var results = [
for(c of customers)
if (c.city == "Seattle")
{ name: c.name, age: c.age }
]
// Generator comprehensions
var results = {
for(c of customers)
if (c.city == "Seattle")
{ name: c.name, age: c.age }
}
unicode
•
•
•
•
Non-breaking additions to support full
Unicode
New RegExp mode to handle code
points
Several new libraries to support
processing strings as 21bit code points
Goal: Support building global apps in
JavaScript
•
see also TC39 i18n library working
group
// 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);
}
modules
•
•
•
•
•
Language-level support for modules
Codify patterns from popular JavaScript
module loaders (AMD, CommonJS)
Host-defined default loader
Implicitly async model – no code
executes until requested modules are
available and processed
Goal: Enable component definition and
usage
// lib/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
// app.js
module math from "lib/math”;
alert("2π = " + math.sum(math.pi, math.pi));
// otherApp.js
import {sum, pi} from "lib/math”;
alert("2π = " + sum(pi, pi));
modules (2)
•
Default export
•
•
•
•
•
•
A single anonymous exported value
Imported with ‘import foo from …”
Imagine that jQuery might be a default
export
Library author must decide – default
export or multi-export?
‘export *’ to auto-re-export
No ‘import *’ yet
•
This can be brittle with versioning
// lib/mathplusplus.js
export * from "lib/math”;
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
// app.js
module math from "lib/mathplusplus”;
import exp from "lib/mathplusplus”;
alert("2π = " + exp(math.pi, math.e));
module loaders
•
•
•
•
•
Dynamic loading
State isolation
Global namespace isolation
Compilation hooks
Nested virtualization
•
Goal: Support code loading natively in
the JavaScript engine
// 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({$: $}))
The rest…
•
•
•
New Math, Number, String and Object APIs
Reflect API
RegExp extensions (/y, /u)
ES7?
•
•
•
•
•
•
Object.observe
async/await
Weak References
Parallel JavaScript
Decorators
Value objects (int64 and bignum)
Q&A
git.io/es6features
[email protected]
Descargar

ECMAScript 6