Hacking with ES6

by @chambaz

Feat. Harry Kane

Disclaimer

I am not an expert.

History

A brief history of JavaScript...

  • 1995 LiveScript released and later renamed to JavaScript
  • 1997 ECMAScript 1 (ES1) officially released 
  • 1999 saw big improvements with ES3
  • DRAMA! ES4 abandoned
  • 2009 TC39 resolves differences and ES5 released
  • 2014 ES6 frozen
  • Now called JS2015 (smh)

Why Now?

I can haz ES6?!...

  • Browsers are starting to implement ES6 features
  • Firefox is the furthest along followed by Chrome 
  • Transpilers, Babel, Traceur
  • Preparing for the future and Angular 2.0

No.

It's all about preparation...

Features

Short hand Objects

Object literal properties

var obj = {

    // old way
    doSomething: function() {

    },

    // new way
    doSomething() {

    },

    // old way
    something: something,

    // new way
    something

};

Constants

ES5 - The old way

var SOMETHING_IMPORTANT = 1;

SOMETHING_IMPORTANT = 2;

SOMETHING_IMPORTANT === 1; // false

ES5 - The actual old way

Object.defineProperty(window, "SOMETHING_IMPORTANT", {
    value:        1,
    writable:     false,
    configurable: false
});

ES6 - The new way

const SOMETHING_IMPORTANT = 1;

SOMETHING_IMPORTANT = 2;

SOMETHING_IMPORTANT === 1; // true

ES6 - Constant anythings

const IMPORTANT_FUNCTION = function() {

    return 'Anything can be assigned to constants';

};

Block Scoping

ES5 - Two kinds of scope

var i = 1;

if(i) {
   var i = 2;
}

i === 1; // false

ES6 - Three kinds of scope

let i = 1;

if(i) {
    let i = 2;
}

i === 1; // true

ES5 - Two kinds of scope

function foo() { 
    return 1; 
}

{
    function foo() { 
        return 2;
    }
       
    foo() === 2; // true
}

foo() === 1; // false

ES6 - Three kinds of scope

function foo() { 
    return 1; 
}

{
    function foo() { 
        return 2;
    }
       
    foo() === 2; // true
}

foo() === 1; // true

Arrow Functions

ES5 - Anonymous functions

(function(x, y, z) {
    x++;
    return x + y + z;
});

ES6 - Shorter syntax

(x, y, z) => {
    x++;
    return x + y + z;
};

ES6 - Even shorter syntax

(x, y, z) => x + y + z;

ES5 - Remember this?

function foo() {
    var that = this;

    setTimeout(function() {
        return that.something;
    }, 200);
}

ES5 -Slightly better

function foo() {
    setTimeout(function() {
        return this.something;
    }.bind(this), 100);
}

ES6 - Inherit scope

function foo() {
    setTimeout(() => this.something, 100);
}

Parameters

ES5 - "default" params

function foo(x, y) {

    if(!x) {
        x = 10;
    }

    if(!y) {
        y = 15;
    }

    return x + y;

}

ES6 - Actual defaults

function foo(x = 10, y = 15) {
    return x + y;
}

ES6 - Rest params

function foo(x, ...y) {
    return x + y.length;
}

foo('Digital Surgeons',1,2,3,4,5) // Digital Surgeons5

ES5 - "Rest" params

function foo(x) {
    var y = Array.prototype.slice.call(arguments, 1);
    return x + y.length;
}

foo('Digital Surgeons',1,2,3,4,5) // Digital Surgeons5

ES6 - Spread params

function foo() {
    return arguments.length;
}

var params = [4, 5, 6];
foo('Digital Surgeons', ...params); // 4

ES5 - "Spread" params

function foo() {
    return arguments.length;
}

var params = [4, 5, 6];
foo.apply(undefined, ['Digital Surgeons'].concat(params)); // 4

Template Strings

ES6 Has Templates!

ES5 - String concat hell

var player = {
        name: 'Harry Kane',
        team: 'Spurs',
        goals: 21
    },

    message = player.name + ' of ' + 
              player.team + ' scored ' + 
              player.goals + ' in 2014/15';  

ES6 - Native templating

let player = {
        name: 'Harry Kane',
        team: 'Spurs',
        goals: 21
    },

    message = `${player.name} of ${player.team} scored ${player.goals} in 2014/15`;  

ES6 - Line breaks ftw

let player = {
        name: 'Harry Kane',
        team: 'Spurs',
        goals: 21
    },

    message = `${player.name} of 
               ${player.team} scored 
               ${player.goals} in 2014/15`;


// Harry Kane of
//             Spurs scored
//             21 in 2014/15

Modules

ES6 Has Modules!!

ES5 - Browserify

// utils.js
module.exports.add(x, y) {
    return x + y;
}

module.exports.subtract(x, y) {
    return x - y;
}

// something.js
var utils = require('lib/utils.js');
utils.add(1, utils.subtract(3, 1)) // 3

ES6 - Native modules

// utils.js
export add(x, y) {
    return x + y;
}

export subtract(x, y) {
    return x - y;
}

// something.js
import add from 'lib/utils.js';
add(1, 2) // 3

// something-else.js
import * from 'lib/utils.js';
add(1, subtract(3, 1)) // 3

Classes

ES6 Has Classes!!

Kinda

ES5 - Object Oriented JS

function MyClass(name) {
    if(!name) {
        name = 'Chambaz';
    }

    this.tmpl = 'Hello ';
    this.name = name;
}

MyClass.prototype.printName = function() {
    return this.tmpl+this.name;
};

var myClass = new MyClass('Digital Surgeons');
myClass.printName(); // Hello Digital Surgeons

ES6 - Syntatic Sugar

class MyClass {

    constructor(name = 'Chambaz') {
        this.tmpl = 'Hello ';
        this.name = name;
    }

    printName() {
        return this.tmpl+this.name;
    }
}

var myClass = new MyClass('Digital Surgeons');
myClass.printName(); // Hello Digital Surgeons

ES5 - Prototypal Inheritance

// have to redefine constructor
function MyOtherClass(name) {
    if(!name) {
        name = 'Chambaz';
    }

    this.tmpl = 'Hello ';
    this.name = name;
}

MyOtherClass.prototype = Object.create(MyClass.prototype);
MyOtherClass.prototype.constructor = MyOtherClass;

MyOtherClass.prototype.printNameNew = function() {
    return this.printName()+', how\'d you like dat inheritence doe'; 
};

var myOtherClass = new MyOtherClass('Digital Surgeons');
myOtherClass.printNameNew(); // Hello Digital Surgeons, how'd you like dat inheritence doe

ES6 - Syntatic sugar

class MyOtherClass extends MyClass {
    printName() {
        let printed = super.printName();
        return `${printed}, how'd you like dat ES6 doe`;
    }
}

var myOtherClass = new MyOtherClass('Digital Surgeons');
myOtherClass.printName(); // Hello Digital Surgeons, how'd you like dat ES6 doe

ES5 - Static methods

function MyClass(name) {
    if(!name) {
        name = 'Chambaz';
    }

    this.tmpl = 'hello ';
    this.name = name;
}

MyClass.doSomethingNow = function() {
    return 'Alright, call it soccer then';
};

MyClass.doSomethingNow(); // Alright, call it soccer then

ES6 - Syntatic sugar

class MyClass {

    constructor(name = 'Chambaz') {
        this.tmpl = 'Hello ';
        this.name = name;
    }

    printName() {
        return this.tmpl+this.name;
    }

    static doSomethingNow() {
        return 'Alright, call it soccer then';
    }
}

myClass.doSomethingNow(); // Alright, call it soccer then

ES5 - Getters / setters

var myObj = {
    
    a: 10,

    get b() {
        return this.a + 1;
    },

    set c(x) {
        this.a = this.a + x;
    }

};

myObj.b // 11

myObj.c = 10;

myObj.a // 20

ES6 - True getters / setters

class MyClass {

    constructor(a = 10) {
        this.a = a;
    }

    get a() {
        return this.a + 1;
    }

    set b(x) {
        this.b = this.a + x;
    }

}

var myClass = new MyClass(1);

myClass.a // 2

myClass.b = 10;

myClass.b // 11

Disclaimer

I don't know what I'm talking about

Symbols

ES6 - New primitive type

let symbol1 = Symbol();
let symbol2 = Symbol('Digital Surgeons');
let symbol3 = Symbol('Digital Surgeons');

typeof symbol1 // symbol

symbol1 === symbol2 // false
symbol2 === symbol3 // false

ES6 - Hidden properties

let mySymbol = Symbol('Description');

let obj = {
    // property key is a symbol
    [mySymbol] : 'Something',

    // defined inline
    [Symbol('key')] : 123,

    something : 'Digital',
    else: 'Surgeons'
};

Object.getOwnPropertyNames(obj); // [something, else]

Object.getOwnPropertySymbols(obj); // [Symbol('Description'), Symbol('key')]

Iterators

ES6 - Custom iteration

let obj = {
    data: ['Digital', 'Surgeons'],
    
    [Symbol.iterator]() {

        const self = this;
        let index = 0;

        return {

            next() {

                if (index < self.data.length) {

                    return {
                        value: `We are ${self.data[index++]}`
                    };

                } else {
                    return { done: true };
                }
            }

        };
    }
};

ES6 - Custom iteration

for (let x of obj) {
    console.log(x);
}

// We are Digital
// We are Surgeons

Generators

ES6 - Cooperative functions

function *foo() {
    var x = 1 + (yield "foo");
    return x;
}

foo() // NOTHING!

ES6 - Generator Iterator

function *foo() {
    var x = 1 + (yield "foo");
    return x;
}

var something = foo();

something.next(); // { value: "foo", done: false }
something.next(10); // { value: 11, done: true }

ES6 - Remember iterators

function *foo() {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
    return 5;
}

for(let x of foo()) {
    console.log(x); // 1, 2, 3, 4, 5
}

ES6 - Delegating generators

function *foo() {
    yield 3;
    yield 4;
}

function *bar() {
    yield 1;
    yield 2;
    yield *foo(); // `yield *` delegates iteration control to `foo()`
    yield 5;
}

for (var v of bar()) {
    console.log(v);
}
// 1 2 3 4 5

Wait for it...

Async Generators

// handle AJAX request and call next() when complete
function request(url) {
    $.get(url, function(response){
        it.next(response);
    });
}

// async generator
function *main() {
    // pause here until the first request completes
    var result1 = yield request("http://some.url.1");
    var data = JSON.parse(result1);

    // pause here until second request completes
    var result2 = yield request("http://some.url.2?id=" + data.id);
    var resp = JSON.parse( result2 );
    console.log( "The value you asked for: " + resp.value );
}

// get it all started
var it = main();
it.next();

Waaaaa?!

...and many more!

Math Functions

Math.sign(-8) // -1
Math.sign(3) // 1

Math.trunc(3.1) // 3

Math.cbrt(8) // 2

String Functions

'Digital Surgeons'.startsWith('Digital') // true

'Digital Surgeons'.endsWith('Surgeons') // true

'Digital Surgeons'.includes('Surge') // true

...plus

Mooney's FavoUrite

'Mooney '.repeat(999);

/*
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney
Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney Mooney

Further reading

Hack time!

ES6

By Adam Chambers

ES6

  • 1,053