Introduction to ECMAScript 6

Christophe Coenraets
@ccoenraets

Christophe Coenraets

Boston, MA

Salesforce.com

@ccoenraets

http://coenraets.org

https://github.com/ccoenraets

Agenda

  • Status
  • Variables & Constants
  • Destructuring
  • Arrow Functions
  • Promises
  • Modules
  • Classes
  • Template Strings
  • Generators
  • Collections

Terminology

History

ECMAScript 6 Goals

Better support for:

  1. Complex Apps
  2. Libraries
  3. Code Generators

Avoid fragmentation around core language features

Modules, Promises, Classes, etc.

Backward Compatibility

“Thou shalt not break the web”

i.e. can't change the way var works

When can I use what?

Using ES6 Today

Transpilers

Constants and Variables

var

Function-Scoped

function divide(x, y) {
    if (y !== 0) {
        var result;
        result = x / y;
    }
    return result;
}
console.log(divide(10, 2)); // 5

let

Block-Scoped

function divide(x, y) {
    if (y !== 0) {
        let result;
        result = x / y;
    }
    return result;  // throws Error
}
console.log(divide(10, 2));

const

Block-Scoped

const PI = 3.14159265359;
const COLOR = {
    name: "Red",
    hexValue: "#FF0000"
};

Cannot be reassigned or redeclared

Creating Objects from Variables

ECMAScript 5

var firstName = "Christophe";
var lastName = "Coenraets";
var twitterId = "@ccoenraets";

var speaker = {
    firstName: firstName,
    lastName: lastName,
    twitterId: twitterId
};

Creating Objects from Variables

ES6 Object Literals

let firstName = "Christophe";
let lastName = "Coenraets";
let twitterId = "@ccoenraets";

let speaker = {firstName, lastName, twitterId};

Works with var too

Destructuring

Extract data from arrays or objects using a syntax that mirrors the construction of array and object literals

Creating Variables from Array Elements

ECMAScript 5

var colors = ["red", "green", "blue"];

var primary   = colors[0];
var secondary = colors[1];
var tertiary  = colors[2];

console.log(primary);   // red
console.log(secondary); // green
console.log(tertiary);  // blue

Creating Variables from Array Elements

ES 6 Array Destructuring

var colors = ["red", "green", "blue"];

var [primary, secondary, tertiary] = colors;

console.log(primary);   // red
console.log(secondary); // green
console.log(tertiary);  // blue

Spread Operator

var colors = ["red", "green", "blue", "yellow", "orange"];

var [primary, secondary, ...otherColors] = colors;

console.log(primary);     // red
console.log(secondary);   // green
console.log(otherColors); // [ 'blue', 'yellow', 'orange']

Functions with Multiple Return Values

function getDate() {
    var d = new Date();
    return [d.getDate(), d.getMonth() + 1, d.getFullYear()];
}

var [day, month, year] = getDate();
console.log(day);   // 4
console.log(month); // 5
console.log(year);  // 2015

Creating Variables from Object Properties

ECMAScript 5

var speaker = { firstName: "Christophe",
                lastName: "Coenraets",
                twitterId: "@ccoenraets" };

var firstName = speaker.firstName;
var lastName = speaker.lastName;
var twitterId = speaker.twitterId;

console.log(firstName); // Christophe
console.log(lastName);  // Coenraets
console.log(twitterId); // @ccoenraets

Creating Variables from Object Properties

ES6 Object Destructuring

var speaker = { firstName: "Christophe",
                lastName: "Coenraets",
                twitterId: "@ccoenraets" };

var {firstName, lastName, twitterId} = speaker;

console.log(firstName); // Christophe
console.log(lastName);  // Coenraets
console.log(twitterId); // @ccoenraets
var {fName: firstName, lName: lastName, twId:twitterId} = speaker;
console.log(fName); // Christophe

Arrow Functions

ES5 Function

var greeting = function(message, name) {
    return message + ' ' + name;
}

console.log(greeting('Hello', 'Christophe'));

ES6 Arrow Function

var greeting = (message, name) => {
    return message + ' ' + name;
}
var greeting = (message, name) => message + ' ' + name;
var greeting = name  => 'Hello ' + name;

Another Example

var array = [1, 2, 3];
var total = 0;
array.forEach(function(item) {
    total = total + item;
});
console.log(total);
var array = [1, 2, 3];
var total = 0;
array.forEach(item => total = total + item);
console.log(total);

ECMAScript 5

“var self = this” aka “var that = this”

var obj = {
    init: function () {
        var self = this;
        setTimeout(function() {
            self.doSomething();
        }, 1000);
    },
    doSomething: function() {
        console.log("doing something in ES5");
    }
};
obj.init();

ES 6 Arrow Functions

Lexical “this”

var obj = {
    init: function() {
        setTimeout(() => this.doSomething(), 1000);
    },
    doSomething: function() {
        console.log("doing something in ES6");
    }
};
obj.init();

Default Params

var greeting = (name, msg="Hello") => msg + ' ' + name;

console.log(greeting('Christophe', 'Hi')); // Hi Christophe
console.log(greeting('Christophe'));       // Hello Christophe
Works with "function" too:
function greeting(name, message="Hello") {
    return message + ' ' + name;
}

Promises

Callback Pyramid of Doom

step1(function (value1) {
    step2(value1, function(value2) {
        step3(value2, function(value3) {
            step4(value3, function(value4) {
                // Do something with value4
            });
        });
    });
});

https://github.com/kriskowal/q

Callback Issues

  1. Hard to compose (sequence and parallel)
  2. Hard to handle error
  3. Violates input params/return value semantic

Promise

Proxy for value that's not yet available

q Promises

Using

Q.fcall(step1)
    .then(step2)
    .then(step3)
    .then(step4)
    .then(function(value4) {
        // Do something with value4
    })
    .catch(function(error) {
        // Handle any error from all above steps
    })
    .done();

think of then(handler) as addEventListener("done", handler)

q Promises

Defining

function step1() {
    var deferred = Q.defer();
    FS.readFile("foo.txt", "utf-8", function (error, text) {
        if (error) {
            deferred.reject(new Error(error));
        } else {
            deferred.resolve(text);
        }
    });
    return deferred.promise;
}

jQuery Promises

Using

service.getList()
    .done(function(list) {
        console.log(list);
    })
    .fail(function(error) {
        console.log(error);
    });

jQuery Promises

Defining

function getList() {
    var deferred = $.Deferred();
    if (list) {
        deferred.resolve(list);
    } else {
        deferred.reject("no list");
    }
    return deferred.promise();
}

ECMAScript 6 Promises

Defining

function timeout(millis) {
    var promise = new Promise(function (resolve, reject) {
        setTimeout(function() {
            resolve();
        }, millis);
    });
    return promise;
}

Promisified setTimeout()

ECMAScript 6 Promises

Using

timeout(1000).then(function() {
    console.log('done waiting');
});

Promisified setTimeout()

ECMAScript 6 Promises

Defining Mock Data Service

var employees;

function findAll() {
    return new Promise(function (resolve, reject) {
        if (employees) {
            resolve(employees);
        } else {
            reject("employees is not defined");
        }
    });
}

ECMAScript 6 Promises

Using Mock Data Service

findAll()
    .then(function(employees) {
        console.log(employees);
    })
    .catch(function(error) {
        console.log(error);
    });

Modules

AMD Module

define(function (require) {

    var $ = require('jquery');

    var findAll = function() {
        // implementation
    };

    var findById = function(id) {
        // implementation
    };

    return {
        findAll: findAll,
        findById: findById
    };

});

Common.js Module

var findAll = function () {
    // implementation
};

var findById = function(id) {
    // implementation
};

module.exports = {
    findAll: findAll,
    findById: findById
};

ECMAScript 6 Modules

Defining

// datelib.js
export const today = new Date();

export var shortDate = function() {
    return today.getMonth() + 1 + '/' +
           today.getDate() + '/' +
           today.getFullYear();
}

ECMAScript 6 Modules

Using

import {today, shortDate} from './datelib';
console.log(today);       // Mon May 4 2015 11:04:06...
console.log(shortDate()); // 5/4/2015
import * as date from "./datelib";
console.log(date.today);
console.log(date.shortDate());

ECMAScript 6 Modules

Defining Mock Data Service

export function findAll() {
    // implementation
}

export function findById(id) {
    // implementation
}

export var endpoint = "http://localhost:5000";

ECMAScript 6 Modules

Using Mock Data Service

import * as employeeService from "employee";

employeeService.findAll().then(function(employees) {
    console.log(employees);
});

Classes

ECMAScript 6 Classes

class Mortgage {

    constructor(amount, years, rate) {
        this.amount = amount;
        this.years = years;
        this.rate = rate;
    }

    calculate() {
        // No interest mortgage for ES6 fans
        return this.amount / (this.years * 12);
    }

}

let m = new Mortgage(200000, 30, 3);
console.log(m.calculate());

ECMAScript 6 Classes

class Shape {

    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    render() {
        console.log('Rendering shape');
    }

}

ECMAScript 6 Classes

class Circle extends Shape {

    constructor(x, y, radius) {
        super(x, y);
        this.radius = radius;
    }

    static get pi() {
        return 3.14159265359;
    }

    get circumference() {
        return 2 * Circle.pi * this.radius;
    }

    render() {
        console.log('Rendering circle');
    }

}

ECMAScript 6 Classes

var c = new Circle(0, 0, 10);
console.log(c.x);             // 0
c.x = 5;
console.log(c.x);             // 5
console.log(Circle.pi);       // 3.14159265359
console.log(c.circumference); // 62.8318530718
c.render();                   // Rendering circle

Template Strings

Template Strings

var str = `Hello World!`
console.log(str);
var multiLine = `This is an example
    of a multiline string`;
console.log(multiLine);

String Substitution

var name = "Christophe";
console.log(`Hello, ${name}!`);
var user = {firstName: "Lisa", lastName: "Wong"};
console.log(`Hello, ${user.firstName} ${user.lastName}!`);

Expressions

console.log(`Today is ${new Date()}!`);
var price = 100;
var exchangeRate = 0.89;
console.log(`Price in Euro: ${price * exchangeRate}`);
console.log(`Hello, ${user.firstName} ${user.lastName}!
Today is ${new Date()}`);

Generators

What is a Generator?

Generator Example

function* idMaker(){
    var index = 0;
    while(true) {
        yield index++;
    }
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined

Collections

ES5 "Map"

var settings = {};
settings.server = "http://localhost";
settings.userName = "Christophe";
settings["language"] = "EN";

Keys have to be strings

ES6 Map

var map = new Map();
map.set("server", "http://localhost");
map.set("userName", "Christophe");
map.get("userName");
map.has("userName");
map.delete("userName");

Keys can be anything

WeakMap

Set

Ordered list of unique arbitrary values
var colors = new Set();
cards.add("red");
cards.add("blue");
console.log(colors.size); // 2;
console.log(colors.has("red")); // true;
items.delete("red");

WeakSet

Resources

Thanks!

@ccoenraets