20 Jun 2014

ES6 Examples

If you’ve been up-to-date with what’s going on in the JavaScript world then you know that ES6 is currently the new hotness in town. I’m going to be showing examples of some of the nicest features in ES6, which include:

Modules

Export example (math.js):

let notExported = 'abc';
export function square(x) {
    return x * x;
}
export const MY_CONSTANT = 123;

Import example (demo.js):

import {square} from 'math';
console.log(square(3));

// alternatively
import 'math' as math;
console.log(math.square(3));

Classes

Object.assign example:

class Person {
    speak() {
        return 'Howdy';
    }
}

class Job {
    work() {
        return 'Working';
    }
}

Object.assign(Person, Job);

var dexter = Object.create(Person);

dexter.speak(); // 'Howdy'
dexter.work(); // 'Working'

Literal example:

var person = {
    type: 'human',
    speak() {
        return 'Howdy';
    }
};

var dexter = Object.create(person);

dexter.speak(); // 'Howdy'

Object.setPrototypeOf example:

class Person {
    speak() {
        return 'Howdy';
    }
}

class Job {
    work() {
        return 'Working';
    }
}

var dexter = Object.create(Person);
var job = Object.create(Job);

Object.setPrototypeOf(dexter, job);

dexter.speak(); // 'Howdy'
dexter.work(); // 'Working'

Setter and Getter example:

class Speaker(name) {
    this.name = name;
    this.years = 0;

    speak(message) {
        return `${this.name}: ${message}`;
    }

    get age() {
        return this.years();
    }

    set age(years) {
        if (Number.isFinite(years)) {
            this.years = years;
        }
    }
}

Static methods example:

class Point {
    static zero() {
        return new Point(0,0);
    }
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
}

let p = Point.zero();

Extends example:

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toString() {
        return '(' + this.x + ', ' + this.y + ')';
    }
}

console.log((new Point(1,2)).toString()); // (1,2)

class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y); // same as super.constructor(x, y)
        this.color = color;
    }
    toString() {
        return this.color + ' ' + super();
    }

Arrow Functions

Filter example:

[1,2,3].filter(value => value % 2); // [1, 3]

Identity example:

let identity = (() => ({'toString': () => { return 'Kit' } }));

console.log(`${identity()}`); // 'Kit'

Sum squares example:

let sumSquares = [for (x of [1,2,3]) x*x].reduce((a, b) => a + b);

console.log(sumSquares); // 14

Generator example:

let idGenerator = (id=0)=>
    (resetId = () => 0,
     nextId = ()=> id++,
     {resetId, nextId});

var nextFrom1000 = idGenerator(1000);

console.log(nextFrom1000.nextId()); // 1000

this example:

function component() {
    let button = document.getElementById('button');
    this.handleClick = function() {

    };
    button.addEventListener('click', () => {
        // no more that = this
        this.handleClick();
    });
}

Destructuring

Simple example:

var vals = [1,2];

var [a,b] = vals;

console.log(a); // 1
console.log(b); // 2

Object example:

var {parse, stringify} = JSON;

console.log(parse); // Function
console.log(stringify); // Function

Extract example:

let obj = {first: 'Dexter', last: 'McPherson'};

let {first: f, last: l} = obj;

console.log(f,' ', l);

Name parameters example:

function fun(arg0, {opt1, opts2}) {
    return [opt1, opt2];
}
// {opt1, opt2} is the sames as {opt1:opt1,opt2:opt2}

fun(0,{opt1:'a',opt2:'b'}); // ['a','b']

Complex object example:

var authors = [
    {
       'name': 'Dav Pilkey',
       'books': [{
           'title': 'Captain Underpants',
           'date': 1997
        }]
   },
   {
       'name': 'Jeff Kinney',
       'books': [{
            'title': 'Diary of a Wimpy Kid',
            'date': 2007
       }]
    }
];

var [{'name': author, 'works': [,{title,date}]}] = authors;

var str = `"${title}", by ${author}, was published in ${date}.`

console.log(str); // '"Captain Underpants", by Dav Pilkey was published in 1997.'

Exclude example:

var [,a,b] = ['foo','bar','qux'];

console.log(a); // 'bar'
console.log(b); // 'qux'

Refutable example:

// refutable (default)
{a: x, b: y} = {a: 3}; // fails

// irrefutable
{a: x, ?b: y} = {a: 3}; // x = 3, y = undefined

// default value
{a: x, b: y=5} = {a: 3}; // x = 3, y = 5

Rest example:

let [x, y, ..rest] = ['a', 'b', 'c', 'd'];
// x = 'a', y = 'b', rest = ['c','d']

Arrow function example:

var headers = {
    'Content-Type': 'application/json'
}

({'request': {headers}}) => headers

console.log(request['Content-Type']); // 'application/json'

Generators

Simple example:

function* zeroOneTwo() {
    yield 0;
    yield 1;
    yield 2;
}

var generator = zeroOneTwo();

for (var i of generator) {
    console.log(i);
}

Take example:

function* count(start) {
    let i = start || 0;
    while(true) {
        yield i++;
    }
}

function* take(iterable, numToTake) {
    var i = 0;
    for (var taken of iterable) {
        if (i++ === numToTake) {
            return;
        }
        yield taken;
    }
}

for (var i of take(count(10), 5)) {
    console.log(i); // 10, 11, 12, 13, 14
}

Iterator example:

function* argumentsGenerator() {
    for (let i = 0; i < arguments.length; i += 1) {
        yield arguments[i];
    }
}

var it = argumentsGenerator('a','b','c');

console.log(it.next()); // { value: 'a', done: false }
console.log(it.next()); // { value: 'b', done: false }
console.log(it.next()); // { value: 'c', done: false }
console.log(it.next()); // { value: undefined, done: true}



for (let value of it) {
    console.log(value); // 'a'
}

Fibonacci example:

function* fibonacci() {
    var previous = 0, current = 1;
    while (true) {
        var temp = previous;
        previous =  current;
        current = temp + current;
        yield current;
    }
}

for (var i of fibonacci()) {
    console.log(i); // 1, 2, ... Infinity
}

Fibonacci destructuring example:

function* fibonacci() {
    let a = 0, b = 1;

    while(true) {
        yield a;
        [a, b] = [b, a + b];
    }
}

for (let value of fibonacci()) {
    console.log(value);
}

Power example:

var pow = (function *() {
    return Math.pow(yield 'x', yield 'y');
}());

// first next must be empty to initialize iterator
console.log(pow.next()); // { value: 'x', done: false }
console.log(pow.next(2)); // { value: 'y', done: false }
console.log(pow.next(3)); // { value: 8, done: true }

Throw example:

function* demo() {
    yield 10;
}

var d = demo();
console.log(d.next()); // value: 10, done: false }
d.throw(new Error('foo')); // Error: foo

Value example:

function* demo() {
    var res = yield 10;
    return 42;
}

var d = demo();
var resA = d.next();
console.log(resA); // { value: 10, done: false }
var resB = d.next();
console.log(resB); // { value: 42, done: true }

Promises

Simple example:

var p = new Promise(function(resolve, reject) {
    resolve('a');
});

Promise.then(function(val) {
    console.log(val); // 'a'
}, function(err) {
    console.error(err);
});

Promise.all example:

var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, 'one'); });
var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'two'); });

Promise.all([p1, p2]).then(function(values) {
    console.log(values); // ['one', 'two']
});

Promise.race example:

var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, 'one'); });
var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'two'); });

Promise.race([p1, p2]).then(function(value) {
    console.log(value); // 'two'
});

Async example:

var fs = require('fs');
var path = require('path');
var Promise = require('es6-promise').Promise;

function async(makeGenerator) {
    return function() {
        var generator = makeGenerator.apply(this, arguments);

        function handle(result) {
            if (result.done)  return result.value;

            return result.value.then(function(res) {
                return handle(generator.next(res));
            }, function(err) {
                return handle(generator.throw(err));
            });
        }

        return handle(generator.next());
    };
}

function readJSON(filename) {
    return readFile(filename, 'utf8').then(JSON.parse);
}

function readFile(filename, enc) {
    return new Promise(function(fulfill, reject) {
        fs.readFile(filename, enc, function(err, res) {
            if (err) reject(err);
            else fulfill(res);
        });
    });
}

readJSON(path.resolve('test.json')).then(function(data) {
    console.log(data);

Proxies

Smart array example:

function smartArray(arr) {
    return Proxy(
        arr,
        {get: function(p,x) {
            if (Number(x) < 0) {
                return p[p.length + Number(x)];
            }
            return p[x];
        }}
    );
}

var arr = smartArray([1,2,3]);

console.log(arr[0]); // 1
console.log(arr[-1]); // 3

Null safe example:

var Obj = Function();
var nullProxy = Proxy(
    {toString: ()=> 'nullProxy'},
    {get: (t,p) => t[p] || new Obj() }
);
Obj.prototype = nullProxy;

var sale = Object.create(nullProxy /*, data */);
var lastName = sale.contact.last.name;
console.log(lastName); // 'nullproxy'

Defaults

Simple example:

function echo(a=1) {
    console.log(a);
}

echo(); // 1
echo(9); // 9

Object example:

function echo({a=1, b=2, c=3}) {
    console.log(a, b, c);
}

echo(); // 1, 2, 3
echo({a:7, b:8, c:9}); // 7, 8, 9

Maps

Simple example:

// map arbitrary values to arbitrary values
let map = new Map();
let obj = {};

map.set(obj, 123);
console.log(map.get(obj)); // 123
console.log(map.has(obj)); // true

map.delete(obj);
console.log(map.has(obj)); // false

Weak Maps

Simple example:

let wm = new WeakMap();

let o1 = {};

wm.set(o1, 'a');

console.log(wm.get(o1)); // 'a'



let wm = new WeakMap();

let o1 = {};

wm.set(o1, 'a');

console.log(wm.get(o1)); // 'a'



let o2 = function(){};

wm.set(o2, 'b');

console.log(wm.get(o2)); // 'b'



let o3 = [];

wm.set(o3, 'c');

console.log(wm.get(o3)); // 'c'



let o4 = new WeakMap();

wm.set(o4, 'd');

console.log(wm.get(o4)); // 'd'



let o5 = 'howdy';

wm.set(o5, 'd');

console.log(wm.get(o5)); // TypeError: Invalid value used as weak map key



let o6 = 123;

wm.set(o6, 'e');

console.log(wm.get(o6)); // TypeError: Invalid value used as weak map key



let o7 = null;

wm.set(o7, 'f');

console.log(wm.get(o7)); // TypeError: Invalid value used as weak map key

Store example:

var storage = new WeakMap();

function store(element, name, value) {
    if (!storage.has(element)) {
        storage.set(element, new WeakMap());
    }

    storage.get(element).set(name, value);
    return element;
}

function retrieve(element, name) {
    if (!storage.has(element)) {
        return;
    }
    return storage.get(element).get(name);
}

function unstore(element, name) {
    if (!storage.get(element)) {
        return;
    }
    let data = storage.get(element);
    let value = data.get(name);
    data.delete(name);
    return value;
}

function clearStore(element) {
    if (!storage.get(element)) {
        return;
    }
    storage.get(element).clear();
}


let el = {}; // Theoretically, this would be a DOM element
let k = {};

store(el, k, 'a');

console.log(retrieve(el, k)); // 'a'

unstore(el, k);

console.log(retrieve(el, k)); // undefined

store(el, k, 'b');

console.log(retrieve(el, k)); // 'b'

clearStore(el);

console.log(retrieve(el, k)); // undefined

Sets

Simple example:

let set1 = new Set();
set1.add('hello');
console.log(set1.has('hello')); // true

let set2 = new Set([3,2,1,'a']);
console.log(set2.values()); // 1,2,3,'a'

Unique values example:

var unique = [...new Set([1, 2, 0, 2, 3, 'A', 'B', 0, 'C', 'C', 'D'])];

console.log(unique); // [1, 2, 0, 3, 'A', 'B', 0, 'C', 'D']

Symbols

Simple example:

let specialMethod = Symbol();
let obj = {
    // computed property key
    [specialMethod]: function(arg) {

    }
};
obj[specialMethod](123);


// short method definition
let obj = {
    [specialMethod](arg) {

    }
};

Shorthand Objects

var name = 'Dexter';
var occupation = 'Scientist';

var result = {name, occupation};

console.log(result); // {name: 'Dexter', occupation: 'Scientist}

Spread Operator

Simple example:

Math.max(...[7,11,4]); // 11

Another example:

function f(x,y,z) {
    console.log(arguments);
}

var args = [0,1,2];

f(...args);




function g(a,b,c,d,e) {
    console.log(arguments);
}

var nums = [1,2,3];

g(0, ...nums, 4);

Rest Operator

Arguments example:

let sum = (...numbers) =>
    numbers.reduce((a,b) => a + b);

// Equivalent to Math.max.apply(null, [4,2,6]) console.log(Math.max(…[4,2,6]));

Constants

Simple example:

const CANT_TOUCH_THIS = 'foo';

console.log(CANT_TOUCH_THIS);

CANT_TOUCH_THIS = 'bar'; // SyntaxError: Assignment to constant variable.

Invalid example:

function f() {
    // with this in place..
    const g = false;

    // you can't do this
    const g = true; // SyntaxError: Variable 'g' has already been declared

    // or this
    g = true; // SyntaxError: Assignment to constant variable.

    // or this
    var g = false; // SyntaxError: Variable 'g' has already been declared

    // or this
    let g = false; // SyntaxError: Variable 'g' has already been declared
}

f();

Block Scoping

Simple example:

{
    let privateKey = Math.random();
    console.log(privateKey); // 0.8486106356140226
}

Reference error:

if (false) {
    var value = 'foo';
    function getValue() {
        return value;
    }
}

getValue(); // ReferenceError: getValue is not defined

Template Strings

Simple example:

var x = 2;
var y = 3;

var equation = `${x} + ${y} = ${x + y}`

console.log(equation); // "2 + 3 = 5"

Object literal example:

var toaster  = {
    food: null,
    toast() {
        return `toasting ${this.food}`;
    }
}

var toaster1 = Object.create(toaster);
var toaster2 = Object.create(toaster);

toaster1.food = 'toast';
toaster2.food = 'bagels';

console.log(toaster1.toast()) // 'toasting toast'
console.log(toaster2.toast()) // 'toasting bagels'

Escape example:

function escape(values, ...substitutions) {
    let {raw, raw: {length}} = values, results = '';
    for (let index = 0; index < length; index++) {
        results += raw[index];
        if (index + 1 == length) {
            break;
        }
        results += String(substitutions[index].replace(/[&<>"'/g,
            (match) => `&#x${match.charCodeAt((0).toString(16)};`)
    }
    return results;
}
let name = 'Kit<script>alert(1)</script>';
escape`<span class="name">${name}</span>`;
// '<span class="name">Kit&#x3c;script&#x3e;alert(1)&#x3c;/script&#3e;</span>'

Conclusion

You can start using ES6 features today. Addy Osmani has a great list of ES6 Tools for transpiling your ES6 code to ES5 so that you can code in the future, while browsers catch up in implementing the spec. You can find all the code examples and more in my es6-examples repo.

What’s your favorite ES6 feature?