ES2015
...and beyond!
Paul Verbeek
nlhtml5.org
ECMAScript
June 1997
August 1998
December 1999
December 2009
June 2011
June 2015
1st edition
ES2, to align with ISO/IEC 16262
July 2008
ES3, added regex, try/catch and more
ES4, Abandoned due to complexity
ES5, strict mode, JSON, get/set, and more
ES5.1, to align with ISO/IEC 16262 3rd edition
ES6/ES2015, a lot of stuff!
ECMA-262
2016
ES2016, not lot of stuff!
(a timeline)
The TC39 process
The TC39 process
Stage 0: Strawman
Free-form ideas, reviewed in TC39 meetings
Stage 1: Proposal
Formally accepted proposal
Stage 2: Draft
Has description of syntax and semantics
Stage 3: Candidate
Spec text complete, has at least 2 implementations
Stage 4: Finished
Ready for standard, passes unit tests
ECMAScript 2015
ECMAScript 2015
-
Arrow functions
-
Binary and Octal Literals
-
Block-scoped variables (let / const)
-
Classes
-
Default + rest + spread parameters
-
Destructuring
-
Enhanced object literals
-
Generators
-
Iterators + for..of
-
Map + Set + WeakMap + WeakSet
ECMAScript 2015
-
new Math + Number + String
+ Array + Object APIs -
Modules
-
Promises
-
Proxies
-
Reflect API
-
Subclassable Built-ins
-
Symbols
-
Tail Calls
-
Template strings
-
Unicode (full support)
ECMAScript 2016
ECMAScript 2016
-
Array.prototype.includes
-
Exponentiation Operator
Block-scoped variables
function logPaul() {
if (true) {
var name = 'Paul Verbeek';
}
console.log(name);
}
logPaul();
Function-scoped variables
function logPaul() {
if (true) {
var name = 'Paul Verbeek';
}
console.log(name); // Paul Verbeek
}
logPaul();
function logPaul() {
var name = undefined;
if (true) {
name = 'Paul Verbeek';
}
console.log(name);
}
logPaul();
Block-scoped variables
function logPaul() {
if (true) {
let name = 'Paul Verbeek';
}
console.log(name); // name is not defined
}
logDan();
function logThePauls() {
let pauls = ['Paul Verbeek',
'Paul McCartney',
'Paul Simon'],
for (let i = 0; i < pauls.length; i++) {
console.log(pauls[i]);
}
console.log(i); // i is not defined
}
logThePauls();
var globalVar = 'global variable';
let globalLet = 'also global';
function f() {
var functionVar = 'function-scoped';
let functionLet = 'this one too';
}
f();
function logPaul() {
let name = 'Paul Verbeek';
let name = 'Paul McCartney';
// Identifier 'name' has already been declared
console.log(name);
}
logPaul();
Block-scoped variables
function logConstantPaul() {
const PAUL = 'Paul Verbeek';
PAUL = 'Paul Simon';
// 'PAUL' is read-only
console.log(PAUL);
}
logConstantPaul();
Block-scoped variables
function logConstantPaul() {
const PAUL = {
firstName: 'Paul',
lastName: 'McCartney'
};
PAUL.lastName = 'Verbeek';
console.log(PAUL.lastName); // Verbeek
}
logConstantPaul();
Block-scoped variables
function logConstantPaul() {
const PAUL = {
firstName: 'Paul',
lastName: 'Verbeek'
};
PAUL = {};
// 'PAUL' is read-only
console.log(PAUL.lastName); // Verbeek
}
logConstantPaul();
Temporal Dead Zone (TDZ)
TEMPORAL
Temporal Dead Zone (TDZ)
console.log(typeof foo); // ReferenceError
console.log(typeof bar); // 'undefined'
let foo = 'inner scope';
Temporal Dead Zone (TDZ)
let foo = 'outer scope';
(function() {
console.log(typeof foo); // ReferenceError
console.log(typeof bar); // 'undefined'
let foo = 'inner scope';
}());
Enhanced object literals
Enhanced object literals
function getPerson(firstName, lastName, age) {
return {
name: fullName + ' ' + lastName,
age,
['is' + firstName]: true,
makeOlder() {
this.age++
}
};
}
const me = getPerson('Paul', 'Verbeek', 29);
me.makeOlder()
console.log(me);
// {"name":"Paul Verbeek","age":30,"isPaul":true}
Template strings
console.log('In ECMAScript 5.1 this
will result in an error.');
// Uncaught SyntaxError: Unexpected token ILLEGAL
console.log(`In ES6 this
will log with a newline.`);
// In ES6 this
// will log with a newline.
A what?
A backtick
or accent grave
So this: `
Instead of this: '
var location = 'Tech Talks',
topic = 'ES6';
console.log('Talking about ' + topic + ' at ' + location);
// Talking about ES6 at Tech Talks
let location = 'Tech Talks',
topic = 'ES6';
console.log(`Talking about ${topic} at ${location}`);
// Talking about ES6 at Tech Talks
Arrow functions
(λ expressions)
1. Less typing
let arr = [1, 2, 3];
let square;
// ES5
square = arr.map(function (a) { return a * a });
// SS6
square = arr.map(a => a * a);
// ES5
function Interface() {
var that = this;
var button = document.getElementById('myButton');
button.addEventListener('click', function () {
console.log('CLICK');
that.handleClick();
});
}
Interface.prototype.handleClick = function () { ... };
// ES6
function Interface {
let button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log('CLICK');
this.handleClick();
});
}
Interface.prototype.handleClick = function () { };
2. no more 'var that = this'
Modules
// modules/math.js
const π = 3.14159265359;
// modules/math.js
export const π = 3.14159265359;
// modules/math.js
export const π = 3.14159265359;
// main.js
import { π } from './modules/math.js';
console.log(π); // 3.14159265359
// modules/math.js
export const π = 3.14159265359;
// main.js
import { π as pi } from './modules/math.js';
console.log(pi); // 3.14159265359
// modules/math.js
export const π = 3.14159265359;
// main.js
import { π as pi } from './modules/math.js';
pi = 3.14; // 'pi' is read-only
// modules/math.js
export const π = 3.14159265359;
export function square(x) {
return x * x;
}
// main.js
import { π as pi, square } from './modules/math.js';
console.log(square(4)); // 16
// modules/math.js
export const π = 3.14159265359;
export function square(x) {
return x * x;
}
// main.js
import * as math from './modules/math.js';
console.log(math.square(4)); // 16
console.log(math.π); // 3.14159265359
// modules/foo.js
export default function() {
console.log('bar!');
}
// script.js
import fooFunc from './modules/foo.js';
fooFunc(); // bar!
Classes
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.fullName = function () {
return this.firstName + ' ' + this.lastName;
};
Person.prototype.toString = function () {
return 'My name is ' + this.fullName();
};
var me = new Person('Paul', 'Verbeek');
console.log(me.toString());
// My name is Paul Verbeek
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName () {
return `${this.firstName} ${this.lastName}`;
}
toString () {
console.log(`My name is ${this.fullName}`);
}
}
let me = new Person('Paul', 'Verbeek');
console.log(me.toString());
// My name is Paul Verbeek
class Person {
...
}
class Employee extends Person {
constructor(firstName, lastName, company) {
super(firstName, lastName);
this.company = company;
}
toString () {
return `${super.toString()}
and I work at ${this.company}`;
}
}
let me = new Employee('Paul', 'Verbeek', 'Booking.com');
console.log(me.toString());
// My name is Paul Verbeek
// and I work at Booking.com
Default, rest & spread parameters
multiply(3); // 6
multiply(3, 3); // 9
function multiply(x, y) {
if (typeof y === "undefined") { y = 2; }
return x * y;
}
multiply(3); // 6
multiply(3, 3); // 9
function multiply(x, y = 2) {
return x * y;
}
multiply(3); // 6
multiply(3, 3); // 9
default
function f(...foo) {
console.log(foo); // [4, 8, 15]
}
f(4, 8, 15);
...spread & ...rest
function f(...foo) {
let numbers = [...foo, 16, 23, 42]
console.log(numbers); // [4, 8, 15, 16, 23, 42]
}
f(4, 8, 15);
function logPaul() {
if (true) {
let name = 'Paul Verbeek';
}
console.log(name); // name is not defined
}
logPaul();
'use strict';
function logPaul() {
if (true) {
var _name = 'Paul Verbeek';
}
console.log(name); // name is not defined
}
logPaul();
function f(...foo) {
let numbers = [...foo, 16, 23, 42]
console.log(numbers); // [4, 8, 15, 16, 23, 42]
}
f(4, 8, 15);
"use strict";
function f() {
for (var _len = arguments.length, foo = Array(_len),
_key = 0; _key < _len; _key++) {
foo[_key] = arguments[_key];
}
var numbers = [].concat(foo, [16, 23, 42]);
console.log(numbers); // [4, 8, 15, 16, 23, 42]
}
f(4, 8, 15);
http://exploringjs.com/
Dr. Axel Rauschmayer
ECMA-262 6th edition
The ECMAScript® 2015 Language Specification
-
Binary and Octal Literals
-
Destructuring
-
Generators
-
Iterators + for..of
-
Map + Set + WeakMap + WeakSet
-
new Math + Number + String
+ Array + Object APIs -
Promises
-
Proxies
-
Reflect API
-
Subclassable Built-ins
-
Symbols
-
Tail Calls
-
Unicode (full support)
What I didn't talk about:
ECMA-262 8th edition
The ECMAScript® 2017
Language Specification
Not really....
Stage 3: Candidate
Spec text complete, has at least 2 implementations
- SIMD.JS - SIMD APIs + polyfill
- Async functions
- Object.values/Object.entries
- String padding
- Trailing commas in function parameter lists and calls
- Object.getOwnPropertyDescriptors()
- function.sent metaproperty
- Rest/Spread properties
- Shared memory and atomics
- Function.prototype.toString revision
Stage 2: Draft
Has description of syntax and semantics
- Additional export-from Statements
- Class and Property Decorators
- Callable class constructors
- ArrayBuffer.transfer
- Observable
- String.prototype.{trimLeft,trimRight}
- Class Property Declarations
- String#matchAll
- System.global
- Asynchronous Iterators
Stage 1: Proposal
Formally accepted proposal
- String.prototype.at
- Set/Map.prototype.toJSON
- Encapsulated private state for objects
- Defensible Classes
- Relationships
- Structured Clone
- WeakRefs
- Annex B - HTML Attribute Event Handlers
- Reflect.isCallable/Reflect.isConstructor
- Additional metaproperties
Stage 0: Strawman
Formally accepted proposal
- Function Bind Syntax
- Do Expressions
- RegExp additions
- Error.isError
- 64-Bit Integer Operations
- Method Parameter Decorators
- Function Expression Decorators
Stage 0: Strawman
Formally accepted proposal
https://github.com/tc39/ecma262
https://tc39.github.io/ecma262/
ECMA-262 7th edition
The ECMAScript® 2016
Language Specification
x ** y
exponentiation operator (**)
Math.pow(x, y)
let a = 3;
a **= 3;
// a = 27
['a', 'b', 'c'].includes('a') // true
['a', 'b', 'c'].includes('d') // false
Array.prototype.includes
['a', 'b', 'c'].indexOf('a') >= 0 // true
['a', 'b', 'c'].indexOf('d') >= 0 // false
['a', 'b', NaN].includes(NaN) // true
['a', 'b', NaN].indexOf(NaN) >= 0 // false
[ , , ].includes(undefined) // => true
[ , , ].indexOf(undefined) >= 0 // => false
@_paulverbeek
@nlhtml5
verbeek.p@gmail.com
2553235
Questions?
ECMAScript 2016 - AMS HTML/CSS
By Paul Verbeek
ECMAScript 2016 - AMS HTML/CSS
- 774