Introduction to ES6

Tommy Cresine

What is ECMAScript?

  • ECMAScript is the underlying core language of JS.
     
  • The features for ES are defined in a standard known as ECMA-262.
     
  • Supersets of ES including Node.js, io.js, and client-side JS add capabilities on top of the core capabilities.
     
  • ES6 also known as ECMA Script Harmony is the latest version and reached completion in 2014. 

Current Compatibility 

Browsers

FF 36 - 65%

Chrome 41 - 45%

IE 11 - 15%

 

Runtimes

io.js - 43%

Node - 25%

PJS - 5%

 

Compilers & Polyfills

Babel + core-js - 76%

Traceur - 64%

Closure - 33%

es6-shim - 21%

JSX- 16%

TypeScript- 9%

Object Literal Changes

let first = 'John';
let last = 'Doe';

let obj = { first, last };

// equivalent to
let obj = { first: first, last: last };

Property Value Shorthands

Method Definitions

let obj = {
    myMethod() {
        return 'foo';
    }
};

//equiv
var obj = {
    myMethod: function() {
        return 'foo';
    }
};
let propKey = 'foo';
    
let obj = {
    [propKey]: true,
    ['b'+'ar']: 123
};

Computed Property Keys

let obj = {
    ['f'+'oo']() {
        return 'bar';
    }
};

console.log(obj.foo()); // bar

Classes

// Superclass
class Person {
    constructor(name) {
        this.name = name;
    }
    describe() {
        return 'Person called ' + this.name;
    }
}

// Subclass
class Employee extends Person {
    constructor(name, title) {
        super(name); 
        this.title = title;
    }
    describe() {
        return super.describe() + ' (' + this.title + ')';
    }
}

//Subclass built-in classes
class AppError extends Error {
    ...
}

Arrow Functions

// More compact syntax
let arr = [1, 2, 3];
let squares = arr.map(x => x * x);

// `this` is picked up from surroundings (lexical)
// Therefore: no more `that = this` or bind()
function UiComponent {

    let button = document.getElementById('myButton');
    
    button.addEventListener('click', () => {
        console.log('CLICK');
        this.handleClick(); // lexical `this`
    });
}

Modules

// lib.js
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}
    
// main.js
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5

Variables, Assigning & Params

// block-scoped let (write) const (read)
function order(x, y) {
    if (x > y) {
        let tmp = x;
        x = y;
        y = tmp;
    }
    // ReferenceError: tmp is not defined
    console.log(tmp===x); 
    return [x, y];
}

//spread operator
let arr = [-1, 7, 2];
// 7
let highest = Math.max(...arr);

// 2011, December 24, 00:00
new Date(...[2011, 11, 24]) 
    
// Non-destructively concatenate elements
// [-1, 7, 2, 9, -6]
let arr2 = [...arr, 9, -6];

//default param values
function initGrid(x=0, y=0) {
    // ...
}
//destructuring
let obj = { first: 'Jane', last: 'Doe' };
// f = 'Jane', l = 'Doe
let { first: f, last: l } = obj;

//named params/options
class Person {
    ...
    displayName({ first: this.fname, last: this.lname } = {}) {
        ...
    }

}

let person = new Person();
person.displayName({ first: 'Joe', last: 'Dirt' });
person.displayName({ last: 'Smith' });

//rest params
function foo(pattern, ...params) {
    return params;
}
// [1, 2]
console.log(foo('bar', 1, 2));

Iterators, Loops & Generators

//for-of loop
let arr = ['foo', 'bar', 'baz'];

for (let element of arr) {
    console.log(element);
}
/* Output:
    foo
    bar
    baz
*/
    
for (let [index,element] of arr.entries()) {
    console.log(`${index}. ${element}`);
}
/* Output:
    0. foo
    1. bar
    2. baz
*/
// Generator function, iterating over obj
function* objectEntries(obj) {
    for (let key of Reflect.ownKeys(obj)) {
        // pause and return a value
        yield [key, obj[key]];
    }
}

let obj = { first: 'Jane', last: 'Doe' };

for (let [key,value] of objectEntries(obj)) {
    console.log(`${key}. ${value}`);
}

/* Output:
    first. Jane
    last. Doe
*/

Template Strings

let name = 'Jane';
let str = `Hi ${name}! 3 plus 4 is ${3+4}`;

let text = `This is a text
that spans
multiple lines.`;

//use tags and tag handlers
safehtml`<a href="${url}">${text}</a>`

Symbols

let obj = {
    data: [ 'hello', 'world' ],
    [Symbol.iterator]() {
        const self = this;
        let index = 0;
        return {
            next() {
                if (index < self.data.length) {
                    return {
                        value: self.data[index++]
                    };
                } else {
                    return { done: true };
                }
            }
        };
    }
};

for (let x of obj) {
    console.log(x);
}
// Output:
// hello
// world

Proxies

let target = {};
let handler = {
    get(target, propKey, receiver) {
        console.log('get ' + propKey);
        return 123;
    }
};
let proxy = new Proxy(target, handler);


/** In console **/
> proxy.foo
    get foo
    123

Utility Methods

//Object.assign
class Point {
    constructor(x, y) {
        Object.assign(this, { x, y });
        // ES6: { x, y } is abbrev. for { x: x, y: y }
    }
}

//Array.prototype.findIndex
> [6, 8, -5].findIndex(x => x < 0)
    2
> [6, 8, 5].findIndex(x => x < 0)
    -1

//Array.prototype.fill
> ['a', 'b', 'c'].fill(7)
    [ 7, 7, 7 ]
> new Array(3).fill(7)
    [ 7, 7, 7 ]

//new String methods
> 'hello world'.startsWith('hello')
    true
> '*'.repeat(5)
    '*****'

Collections

/** Arbitrary values Map keys **/ 
> let obj = {};
> let map = new Map();
    
> map.set(obj, 123);
> map.get(obj)
    123
> map.has(obj)
    true
> map.delete(obj);
    true
> map.has(obj)
    false

/** Sets are unique collections **/
let arr = [5, 1, 5, 7, 7, 5];
let unique = [...new Set(arr)]; // [ 5, 1, 7 ]

Promises

function httpGet(url) {
    return new Promise(
        function (resolve, reject) {
            var request = new XMLHttpRequest();
            request.onreadystatechange = function () {
                if (this.status === 200) {
                    // Success
                    resolve(this.response);
                } else {
                    // Something went wrong (404 etc.)
                    reject(new Error(this.statusText));
                }
            }
            request.onerror = function () {
                reject(new Error(
                    'XMLHttpRequest Error: '+this.statusText));
            };
            request.open('GET', url);
            request.send();    
        });
}
//implementation
httpGet('http://site.com/route').then(
    response => {
        console.log('Contents: ' + response);
    },
    error => {
        console.error('Something went wrong', error);
    });

Using ES6 Now

  • Node v0.12.x using --harmony flag
  • io.js v1.x ships with stable ES6 features
  • AngularJS 2.0
  • Aurelia Framework
  • Babel ES6 to ES5 transpiler

Aurelia Framework

Next generation JS client-side framework featuring Web Components, ES6 and more.

  • Written with ES6 & ES7, no dependencies except polyfills.
  • Modular architecture: use-at-will or as full-featured.
  • MV* with conventions over configuration.
  • Dependency Injection Container
  • Advanced Routing / Child Routing
  • Gulp Dev Pipeline & JSPM client-side packages

Thank You

Made with Slides.com