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