ECMAScript

An introduction

Paul Verbeek

  • Only Dutch client-side developer
  • BookingHome Partner Experience
  • Started two weeks ago
  • Now expects a party in the RAI every other week
  • Worked with ES6 at previous job (Randstad)

Data proves (...) cats (..)

- Eduardo Shiota

ECMAScript Harmony

ECMAScript 6

ECMAScript 2015

ECMAScript?

ECMA-262

ECMA-402

Dart Programming Language

ECMA-222

Adaptive Lossless Data Compression Algorithm 

ECMA-74

Measurement of Airborne Noise Emitted by Information Technology and Telecommunications Equipment

ECMA-262

ECMAScript® Language Specification

ActionScript

Adobe ExtendScript

JScript

JScript.NET

V8

SpiderMonkey Chakra

JavaScript

ECMA-262 6th edition

The ECMAScript® 2015 Language Specification

ES6

ECMAScript 5.1

  • strict mode ("use strict")

  • JSON

  • String.trim()

  • getters & setters

  • Function.prototype.bind()
  • New Object methods (e.g. Object.create())

  • New Array methods (e.g. Array.map())

  • Date.now()

ECMAScript 5.1

ECMAScript 6

ECMAScript 6

  • Arrow functions

  • Binary and Octal Literals

  • Block-scoped variables

  • Classes

  • Comprehension

  • Default + rest + spread parameters

  • Destructuring

  • Iterators

  • Generators

  • Map + Set + WeakMap + WeakSet

ECMAScript 6

  • Math + Number + String + Object APIs

  • Modules

  • Promises

  • Proxies

  • Reflect API

  • Subclassable Built-ins

  • Symbols

  • Tail Calls

  • Template strings

  • Unicode

ECMAScript 6

  • Arrow functions

  • Block-scoped variables

  • Classes

  • Default, rest & spread parameters

  • Destructuring

  • Modules

  • Template strings

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';
}());

Destructuring

// Single values
var name = {};
name.first = 'Paul';
name.last = 'Verbeek';
// Single values
var first = name.first;
var last = name.last;
// Single values
var name = {};
name.first = 'Paul';
name.last = 'Verbeek';

// Multiple values
var name = {
 first: 'Paul',
 last: 'Verbeek'
};

Constructing

Extracting

vs.

// Single values
var first = name.first;
var last = name.last;


// Multiple values
var ??? = name;

Constructing

Extracting

vs.

// Single values
let name = {};
name.first = 'Paul';
name.last = 'Verbeek';

// Multiple values
let name = {
 first: 'Paul',
 last: 'Verbeek'
};
// Single values
let first = name.first;
let last = name.last;


// Multiple values
let { first, last } = name;
let name = {
 first: 'Paul',
 last: 'Verbeek'
};


let { first: firstName, last: lastName } = name;

// firstName = 'Paul'
// lastName = 'Verbeek'

Objects

function logName({ first: firstName, 
                   last: lastName }) {
  console.log(firstName, lastName);
}

let name = {
 first: 'Paul',
 last: 'Verbeek'
};


logName(name);
// Paul, Verbeek
let nameArr = ['Paul', 'Verbeek'];

let [firstName, lastName] = nameArr;
 // firstName = 'Paul', lastName = 'Verbeek'

Arrays

let nameArr = ['Paul', 'Verbeek'];

let [firstName, lastName] = nameArr;
 // firstName = 'Paul', lastName = 'Verbeek'

[firstName, lastName] = [lastName, firstName];
 // firstName = 'Verbeek', lastName = 'Paul'
let nameArr = ['Paul', 'Verbeek'];

let [firstName, lastName] = nameArr;
 // firstName = 'Paul', lastName = 'Verbeek'

[firstName, lastName] = [lastName, firstName];
 // firstName = 'Verbeek', lastName = 'Paul'

let [all, day, month, year] =
 /^(\d\d)-(\d\d)-(\d\d\d\d)$/
 .exec('28-08-2015');

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!

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'

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

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

ECMAScript 6

ECMAScript 2015

ECMAScript Harmony

ECMA-262 6th edition

The ECMAScript® 2015 Language Specification

  • Binary and Octal Literals

  • Comprehension

  • Iterators

  • Generators

  • Map + Set + WeakMap + WeakSet

  • Math + Number + String + Object APIs

  • Promises

  • Proxies

  • Reflect API

  • Subclassable Built-ins

  • Symbols

  • Tail Calls

  • Unicode

  1. Easier to write
  2. Easier to maintain
  3. Faster code execution (eventually)

How are we going to use this at Booking.com?

¯\_(ツ)_/¯

ECMAScript 2015 - Booking.com

By Paul Verbeek

ECMAScript 2015 - Booking.com

  • 754