ES6

ES2015

ES*mumble*

JavaScript

ES3 - 1999

ES5 - 2009

ES6 - 2015

ES7 - 2016

In 2016, we’ll be publishing ES 2016, and ES 2015 will be missing a lot of stuff that ES 2016 has

– Domenic Denicola

ES6 is already in browsers!

Show me the features!

Class Syntax

Syntactic sugar for Object.prototype

class Cat {
    constructor(name) {
        this.name = name
    }

    speak() {
        console.log('Bark, woof')
    }
    
    attack(enemy) {
        console.log('Feed me')
    }
}
function Cat(name) {
    this.name = name
}

Cat.prototype.speak = function() {
    console.log('Bark, woof')
}

Cat.prototype.attack = function(enemy) {
    console.log('Feed me')
}

ES6

ES5

Default Function Parameters

function animalMood(mood = 'Happy', animal = 'Taniwha') {
    return mood + ' ' + animal
}

animalMood()                   // "Happy Taniwha"
animalMood('Angry')            // "Angry Taniwha"
animalMood(undefined, 'Snake') // "Happy Snake"
animalMood('Yappy', 'Dog')     // "Yappy Dog"
function animalMood() {
    var mood = arguments[0] === undefined ? 'Happy' : arguments[0]
    var animal = arguments[1] === undefined ? 'Taniwha' : arguments[1]

    return mood + ' ' + animal
}

ES6 Modules

Standardised protocol for writing modular code

class CatAPI {
    fetch(limit) {
        // ...
    }

    fetchAll() {
        // ...
    }
}

export default new CatAPI()
import cats from './cat-api'
import { foo, baz } from './utils'

let cats = cats.fetchAll().map(foo)
export {
    foo: function() {},
    bar: function() {},
    baz: function() {}
}

main.js

cat-api.js

utils.js

Fat Arrow Syntax

Lexically-scoped, prototype-less functions

let square = x => x * x
// Implicit return
// Single parameter; optional brackets



[1, 2, 3, 4].reduce((p, c) => p + c)
// Brackets for multiple params




setTimeout(() => {
    console.log('Mathematical!')
})
// No implicit return with block syntax
var square = function (x) {
    return x * x
}



[1, 2, 3, 4].reduce(function (p, c) {
    return p + c
})



setTimeout(function() {
    console.log('Mathematical!')
})

ES6

ES5

var lemongrab = {
    punishment: 'One million years dungeon!',

    givePunishment: function() {
        setTimeout(function() {
            // this === window/global
            console.log(this.punishment) // undefined :(
        }, 1000)
    }
}

Dynamic this binding

var lemongrab = {
    punishment: 'One million years dungeon!',

    givePunishment: function() {
        var _this = this; // yuck

        setTimeout(function() {
            console.log(_this.punishment) // One million years dungeon!
        }, 1000)
    }
}

Dynamic this binding

var lemongrab = {
    punishment: 'One million years dungeon!',

    givePunishment: function() {
        setTimeout(function() {
            console.log(this.punishment) // One million years dungeon!
        }.bind(this) /* ick */, 1000)
    }
}

Dynamic this binding

var lemongrab = {
    punishment: 'One million years dungeon!',

    givePunishment: function() {
        setTimeout(() => {
            // this === lemongrab
            console.log(this.punishment) // One million years dungeon!
        }, 1000)
    }
}

Lexical this binding

Block Scope

let / const

for (var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i)
    }, 1000)
}

// 10, 10, 10, 10, 10, 10, 10, 10, 10, 10

JavaScript's scoping can cause unexpected behaviour

wat

for (var i = 0; i < 10; i++) {
    (function (i) {
        setTimeout(function () {
            console.log(i)
        }, 1000)
    })(i)
}

// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

We tend to use closures to work around this

yuck

for (let i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i)
    }, 1000)
}

// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

But what we really need is block scope

\o/

Array Comprehensions

var numbers = [1, 2, 3, 4]

[for (n of numbers) n * 2]
// [2, 4, 6, 8]



[for (n of numbers) if (n < 3) n]
// [1, 2]



[for (n of numbers) if (n > 2) n + 1]
// [4, 5]
var numbers = [1, 2, 3, 4]

numbers.map(function(n) {
    return n * 2
})
// [2, 4, 6, 8]

numbers.filter(function(n) {
    return n < 3
})
// [1, 2]

numbers.filter(function(n) {
    return n > 2
}).map(function(n) {
    return n + 1
})
// [4, 5]

Array comprehensions

Array.map / Array.filter

Template Strings

Multi-line strings with interpolation

var cows = ['bertha', 'hoani', 'daisy', 'harold', 'tama']

console.log(`I have ${cows.length} cows, but I want ${cows.length + 2}!

My favourite is ${cows[0]}.`)

// "I have 5 cows, but I want 7!
//
// My favourite is bertha."

Destructuring assignment

// Array matching
let [x, y] = [22, 18]
console.log(x, y) // 22, 18

let [a, , b] = [1, 2, 3]
console.log(a, b) // 1, 3

// Using the splat operator
let [a, b, ...c] = [1, 2, 3, 4, 5]
console.log(a, b, c) // 1, 2, [3, 4, 5]


// Object matching
{ a, b } = { a: 'foo', b: 'bar' }
console.log(a, b) // "foo", "bar"

So much more...

Iterators & generators

Splat/spread operators

Map, Set, Symbol

Promise API

WeakMap, WeakSet

Real unicode support

Tail call optimisation
Proxy objects

Reflection API