ECMAScript 6

The Future of JavaScript

ECMAScript

May 1995 - Created at Netscape : "Mocha"

September 1995 - Shipped in Netscape 2.0 : "LiveScript"

December 1995 - Renamed to "JavaScript"

August 1996 - Cloned in Microsoft IE 3.0 : "JScript"

1996..1997 - ECMA-262 Ed.1 Standard: ES 1

1998 - ES 2

1999 - ES 3 : Modern JS

2000 - ES 4 (Attempt 1)

2005..2007 - ES 4 (Attempt 2)

2008 - ES 4 Abandoned

2009 - ES 5: "use strict", JSON, Object.create, ...

2011 - ES 5.1

2014 - ES Harmony

Harmony Goals

Fix things: scoping, memory management, ...

Improve productivity

Better readability / Easier maintenance

Programming in the large

Standardization: Classes, Promises, ...

Library/Framework Development

ES 2015

Current State

Proposals freezed, Specification not finalized yet

March 2015: Publication process starts, June 2015: Formal publication

Browser Support

IE Technical Preview69%
Firefox 3768%
Chrome 4248%

Runtimes

io.js47%
NodeJS29%

Transpilers

6to578%
Traceur61%
ES6 Transpiler26%

ES6 Support

What's New

Syntactic Sugars

Arrow Functions, Destructuring, Rest Parameters, ...

New Language Features

Block Scoping, Classes, Modules, Generators, ...

Runtime Additions

WeakMap, WeakSet, Reflect, Promise, ...

Syntactic Sugars

Default Parameters

Old Way


function increment(x, step) {
    if(typeof step === "undefined") {
        step = 1;
    }

    return x + step;
}
                            

Default Parameters

ES6 Way


function increment(x, step = 1) {
    return x + step;
}

increment(3) == 4
increment(3, 10) == 13
                            

Default Parameters

Even Expressions


function insertLog(title, time = Date.now()) {
    ...
}
                            

Better Object Literals

Old Way


var firstname = "John", lastname = "Connor";

var obj = {
    firstname : firstname,
    lastname: lastname,

    toString: function() {
         return this.firstname + ' ' + this.lastname;
    }
};

obj["id_" + getId()] = 42;
                            

Better Object Literals

ES6 Way

                                
var firstname = "John", lastname = "Connor";

var obj = {
    firstname,  // => firstname: firstname
    lastname,

    toString() {
         return this.firstname + ' ' + this.lastname;
    },

    [ "id_" + getId() ]: 42
};
                            

Template Strings

Typical String Concatenation


var piecesPerPie = 6;
var numberOfPies = 3;

console.log('There are ' + numberOfPies + ' pies, so we have ' + 
            (piecesPerPie * numberOfPies) + ' pieces.');
                                        

Template Strings

BACKQUOTE instead of quotes

Template Strings

Using ES6 template strings


var piecesPerPie = 6;
var numberOfPies = 3;

console.log(`There are ${numberOfPies} pies, so we have \
    ${piecesPerPie * numberOfPies} pieces.`);
                                

Template Strings

Multiline Strings


function renderPerson(person) { return `
<dl>
  <dt>First</dt> <dd>${person.first}</dd>
  <dt>Last</dt> <dd>${person.last}</dd>
</dl>
`;
}

renderPerson({first: 'Brian', last: 'Genisio'});
                            

Arrow Functions

Typical Functions


var odds = evens.map(function(v) { return v + 1 });

nums.forEach(function(v) {
  if (v % 5 === 0)
    fives.push(v);
});

var shop = {
    _items: ['iPhone 6', 'iPad Air', 'Nexus 9', 'Kindle Fire'],

    bindEvents: function() {
        var that = this;
        $('#display').click(function(){  // this == button element
            that._items.forEach(function(i){
                $('#products').append('<div>' + i + '</div>');
            });
        });
    }
}
                            

Arrow Functions

ES6 Way


var odds = evens.map(v => v + 1);

nums.forEach(v => {
  if (v % 5 === 0)
    fives.push(v);
});

var shop = {
    _items: ['iPhone 6', 'iPad Air', 'Nexus 9', 'Kindle Fire'],

    bindEvents: function() {
        $('#display').click((ev) => {  // this == shop object
            this._items.forEach(i => $('#products').append('<div>' + i + '</div>');
        });
    }
}
                            

Arrow Functions

Although it is a function, is not a constructor


var func = () => "";
var instance = new func(); // TypeError: func is not a constructor
                            

It has no prototype

func.prototype; // undefined

Rest Parameters


function sum(...numbers) {
  var sum = 0;
  numbers.forEach(number => {
    sum += number;
  });
  return sum;
}

sum(1, 2, 3); // == 6
sum(); // == 0
                            

Rest Parameters

Rest Parameters and Spread


function sum(head, ...tail) {
    if(!tail.length) return head;
    return head + sum(...tail);
}

sum(1, 2, 3); // == 6
sum(); // == 0
                            

Destructuring Assignment

Array Destructuring


var [a, b] = [1,2];
// a == 1, b == 2

var [a, b] = [b, a];
// a == 2, b == 1

function getArray(){
    return [1,2,3,4];
}

var [a,,c,d] = getArray();
// a == 1, c == 3, d == 4
                            

Destructuring Assignment

Object Destructuring


var {firstname: fn, lastname: ln} = 
                {firstname: 'Bruce', lastname: 'Wayne'};
// fn == 'Bruce', ln == 'Wayne'

function getResult() {
    return {
        result: 1234,
        error: null
    };
}

var {result, error} = getResult();
// result == 1234, error == null
                            

Destructuring Assignment

Mixed and Nested


var options = {
    elementId: 'content',
    className: 'blue-content',
    position: [100,200],
    styles: {
        color: 'blue'
    }
};

var {
    elementId: el, 
    position: [x,y], 
    styles : { color: color }
} = options;

// el == 'content', x == 100, y == 200, color == 'blue'
                            

Language Features

let

Typical Function Scopes


function fnScoped() {
    if(true) {
        var zed = 'alive'; // zed is "hoisted" to the function block
    }

    if(true) {
        console.log('zed is ' + zed); // 'zed is alive'
    }
}
                            

let

New ES6 Block Scoping


if(true) {
    let zed = 'alive';
}

console.log('zed is ' + zed); // ReferenceError: zed is not defined
                            

let

Typical Function Scopes


for(var i = 0; i < 10; i++) {
    var button = $('<button>Button #' + i + '</button>');
    button.click(function() { alert(i); });
    $('body').append(button);
}
                            

let

What is happening


var i;
for(i = 0; i < 10; i++) {
    var button = $('<button>Button #' + i + '</button>');
    button.click(function() { alert(i); });
    $('body').append(button);
}
// i == 10
// button.click => alert(i);
                            

let

Using Block Scopes


for(let i = 0; i < 10; i++) {
    let button = $('<button>Button #' + i + '</button>');
    button.click(function() { alert(i); });
    $('body').append(button);
}
                            

const


const MAX_ITEMS = 30;

// Syntax error: missing initialization
const NAME;

if (condition) {
    const BASE_URL = 'http://www.yahoo.com';
    ...
}

// BASE_URL isn't accessible here
                            

const


const foo = {};
foo.prop = 123; // OK, the object is mutable
foo = {}; // TypeError

const bar = [];
bar.push('abc'); // OK, the array is mutable
                            

for-of

Old Style Loops


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

for(var i=0; i<arr.length; i++) {
    console.log(arr[i]);
}

arr.forEach(function(){ console.log(i); });
                            

for-of

Loop over arrays, generators, iterators


let arr = [1, 2, 3, 4];

for(let i of arr){
    console.log(i);
}

// 1, 2, 3, 4
                            

Classes

Classic OOP Programming in JavaScript


function Person(name) { this.name = name; }

Person.prototype.hi = function () {
    return "Hello " + this.name;
};

function Employee(name, title) {
    Person.call(this, name);
    this.title = title;
}
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.hi = function () {
    return Person.prototype.hi.call(this)
           + ", the " + this.title;
};
                            

Classes

OOP Solutions before ES6

YUIhas Y.extend() to perform inheritance.
Prototypehas Class.create() and Object.extend() for working with objects and “classes”.
Dojohas dojo.declare() and dojo.extend().
MooToolshas a custom type called Class for defining and extending classes.
...

Classes

class in ES6


class Person {
    constructor(name) { 
        this.name = name; 
    }

    hi() {
        return `Hello ${this.name}`;
    }
}

let p = new Person('Walter');
p.hi(); // Hello Walter
                            

Classes

class inheritance in ES6


class Employee extends Person {
    constructor(name, title) {
        super.constructor(name);
        this.title = title;
    }
    
    hi() {
        return `${super.hi()}, the ${this.title}`;
    }
}

let p = new Employee('W. White', 'Teacher');
p.hi(); // Hello W. White, the Teacher
                            

Classes


{
    let transformObject = x => x;

    let inst = new MyClass(); // ReferenceError

    // Note the expression in the `extends` clause
    class MyClass extends transformObject(Object) {
    }
}
                            

Modules

Typical File Separation


<script src="lib/math.js"></script>
<script src="lib/jquery.js"></script>

<script>
    $('#pi').text(math.sum(math.pi, math.pi));
</script>
                            

Modules

Asynchronous Module Definition (AMD)

Complicated Syntax / Asynchronous Loading / Main Use in Browsers

require.js


require(["lib/math", "lib/jquery"], 
    function(math, $) {
        $('#pi').text(math.sum(math.pi, math.pi));
    }
);
                                

Modules

CommonJS Modules

Compact Syntax / Synchronous Loading / Main Use on Server

Browserify (CommonJS)


var math = require('lib/math'),
$ = require('lib/jquery');

$('#pi').text(math.sum(math.pi, math.pi));
                                
> browserify main.js -o bundle.js
<script src="bundle.js"></script>

Modules

ES6 Modules (Synchronous)

lib/math.js


export function sum(x, y) {
  return x + y;
}
export const PI = 3.141593;
                            

app.js


import * as math from "lib/math";
import {jQuery as $} from "lib/jquery";
    
$('#pi').text(math.sum(math.PI, math.PI));
                            

Modules

ES6 Modules (Asynchronous)

app.js


System.import('lib/math').then(math => {
    $('#pi').text(math.sum(math.PI, math.PI));
});
                            

Generators


function* generatorFunction() {
    yield 1;
    yield 2;
}

let genObj = generatorFunction();

genObj.next(); // { done: false, value: 1 }
genObj.next(); // { done: false, value: 2 }
genObj.next(); // { done: true }
                            

Generators

function* generatorFunction() {
    yield 1;
    yield 2;
}

let genObj = generatorFunction();

genObj.next(); // { done: false, value: 1 }
genObj.next(); // { done: false, value: 2 }
genObj.next(); // { done: true }

Generators

Using for-of loop


function* gen() {
    yield 1;
    yield 2;
}

for(let i of gen()){
  console.log(i);
}
// 1, 2
                            

Generators

Traversing a Tree


function* traverse(node) {
    if (Array.isArray(node)) { // node
        for(let i=0; i < node.length; i++) {
            yield* traverse(node[i]); 
        }
    } else {
        yield node; // leaf
    }
}

const tree = [ 'a', ['b', 'c'], ['d', 'e'] ];
for(let x of traverse(tree)) {
    console.log(x);
}
                            

Generators

Pausing a function


function* longRunningTask() {
    // do something
    yield; // pause
    // do something
    yield; // pause
}

let task = longRunningTask();

while(!task.next().done) {
    console.log('Next Step...');
}
console.log('Done.');
                            

Generators

Callback Hell


$.ajax(url, {
    success: function(data) {
        $('#result').html(data);
        var status = $('#status').html('Download complete.');
        status.fadeIn({
            complete: function(){
                setTimeout(function(){
                    status.fadeOut();
                }, 2000);
            }
        });
    }
});
                            

Generators

No callback hell!

Flat async code using Promises

taskjs - http://taskjs.org


import spawn from "http://taskjs.org/es6-modules/task.js";

spawn(function*() {
    var data = yield $.ajax(url);
    $('#result').html(data);
    var status = $('#status').html('Download complete.');
    yield status.fadeIn().promise();
    yield sleep(2000);
    status.fadeOut();
});
                            

Runtime Additions

Map / Set

WeakMap / WeakSet

String methods

Array methods

Math, Number Methods

Proxy

Promise

...

How to use ES6?

Build with Transpilers

Run with Transpilers

Use Shims/Polyfills

How to use ES6?

6to5 Transpiler

How to use ES6?

6to5 Command line

Install 6to5

> npm install --global 6to5

Convert ES6 to ES5

> 6to5 script.js > build.js

How to use ES6?

Run with Transpiler

Traceur


<script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
<script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>

<script type="module">
  class Greeter {
    constructor(message) {
      this.message = message;
    }

    greet() {
        console.log(this.message);
    }
  };

  var greeter = new Greeter('Hello, world!');
  greeter.greet();
</script>
                                

Fiddle About with ES6

http://6to5.org/repl

Fiddle About with ES6

ES6 Repl Chrome Extension

Debugging ES6

Transpile using source maps

> 6to5 script.js --out-file build.js --source-maps

Real-world Usage of ES6

  • AngularJS 2.0

    Superheroic JavaScript MVW Framework

  • EmberJS

    A framework for creating ambitious web applications.

  • DOMtastic

    Small & fast DOM and event library for modern browsers.

  • Reapp

    Make beautiful hybrid apps that feel great with React, Webpack and ES6.

  • Koa

    Expressive middleware for node.js using generators to make web applications.

Thank You and Happy Coding!

systemgroup.net/es6

Farshad Sepehrara

farshads@systemgroup.net

Yousef Salimpour

yousefs@systemgroup.net