ECMAScript 2015

JS : Filling the gap

Standard

JS Specification

ECMA International — Organization

Standard 262 : ECMAScript — JS

Technical Committee 39 — Work group

Four stages process — Proposals

 

ES2015 Features

arrows

classes

enhanced object literals

template strings

destructuring

let + const

default + rest + spread

iterators + for..of

generators

unicode

modules

modules loaders

map & set

proxies

core APIs

symbols

subclassable built-ins

promises

reflect API

tail calls

binary and octal literals

let & const

// const & let are scoped at the block level
if(true) {
  let foo = "bar"
}
foo // Error: Can't find variable: foo
 
// const prevents reassignation
const foo = "bar"
foo = "baz" // Error: "foo" is read-only

functions  arrows

var numbers = [1, 2, 3, 4, 5, 6];

// ES5 way
var even = numbers.filter(function(number) {
    return number % 2 === 0; 
});

// ES2015 way
var even = numbers.filter(number => number % 2 === 0);

functions  this

var numberObject = {
    numbers: [],
    getFromServer() {
        // no more var self = this
        $.ajax('http://api.com/numbers', data => {
            this.numbers = data;
        });
    }
}

object literals

var name = "Bob";

var somebody = {
    // New syntax replacing name: name,
    name,
    friends: [],
    // New syntax replacing showFriends: function showFriends() {
    showFriends() {
        console.log(this.name + " knows " + this.friends);
    },
    // Computed property names
    ["prop_" + name]: "computed" 
};

console.log(somebody.prop_Bob); // computed

functions  default

var numbers = [1, 2, 3, 4];

// ES5 way
var incrementArrayValues = function(array, increment) {
    increment = increment || 1;
    return array.map(function(value) {
        return value + increment;
    });
}

// ES2015 way
var incrementArrayValues = (array, increment = 1) => {
    return array.map(value => value + increment);
}

console.log(incrementArrayValues(numbers)); // [2,3,4,5]
console.log(incrementArrayValues(numbers, 2)); // [3,4,5,6]

spread & rest

var fewNumbers = [2, 3, 4];

// Turn an array into consecutive arguments
var threeSum = (x, y, z) => x + y + z;
console.log(threeSum(...fewNumbers)); // 9

console.log([1, ...fewNumbers, 5, 6]); // [1, 2, 3, 4, 5, 6]

// Bind trailing parameters to an array
var incrementValues = (increment = 1, ...values) => {
    return values.map(value => value + increment);
}

console.log(incrementValues(2, 5, 6, 7)); // [7, 8, 9]

destructuring

// binding using pattern matching
var [a, , b, c, d = 5] = [1,2,3];
console.log(a, c === undefined, d); // 1 true 5


var bob = {
    name : "bob",
    friends: [],
    printFriends() { … }
};

var {name, friends: f} = bob;
console.log(name, f); // bob []

template strings

const multiline = `In ES5 this is
 not legal.`


const unread = 1
console.log(`you have ${unread} message${unread !== 1 ? `s` : ``}`)
// you have 1 message

classes

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    // no coma here
    toString() {
        return `(${this.x}, ${this.y})`;
    }
    static distance(a, b) {
        const dx = a.x - b.x;
        const dy = a.y - b.y;
        return Math.sqrt(dx*dx + dy*dy);
    }
}

console.log(new Point(1, 2).toString()); // (1, 2)
console.log(Point.distance({x: 1, y: 3}, {x: 6, y: 7})); // 6.4031242374328485

classes

class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y);
        this.color = color;
    }
    toString() {
        return super.toString() + ` in ${this.color}`;
    }
}

var colored = new ColorPoint(1, 2, 'red');
console.log(colored.toString()); // (1, 2) in red

for ... of

// ES5 way
for (var property in object) {
    if (object.hasOwnProperty(property)) {
        console.log(object[property]);
    }
}
for (var i=0; i<array.length; i++) {
    console.log(array[i]);
}

// ES2015 way
for (let property of object) {
    console.log(object[property]);
}
for (let value of array) {
    console.log(value);
}

map & set

// Sets
var s = new Set();
s.add("foo").add("bar").add("foo");
console.log(s, s.has("foo")); // ["foo","bar"] true

// Maps
var m = new Map();
m.set("foo", 42);
m.set(s, "anything as a key");
console.log(m.get(s)); // anything as a key

weakmap & weakset

var refs = [{}]

// Weak Maps
var wm = new WeakMap();
wm.set(refs[0], "foo");
// Weak Sets
var ws = new WeakSet();
ws.add(refs[0]);

console.log(wm.has(refs[0]), ws.has(refs[0])); // true true
delete refs[0];
console.log(wm.has(refs[0]), ws.has(refs[0])); // false false

modules

// lib/math.js
export function sum(x, y) {
  return x + y;
}
export var pi = 3.141593;

// app.js
import * as math from "lib/math";
console.log("2π = " + math.sum(math.pi, math.pi));

// otherApp.js
import {sum, pi} from "lib/math";
console.log("2π = " + sum(pi, pi));

// no more global variables <3 <3 <3

WAIT A MINUTE.

What about browser support ?

You put ES2015 in

And get ES5 out

ECMAScript 2015

By Thibaut Dutartre