ECMAScript 6

New JavaScript version

Marián Rusnák

WebElement Prešov

May 2015

About me

  • Developing web applications 4+ years

  • PHP, JavaScript, ASP.NET, Java

  • Master's student (final year)

  • Masaryk University, Brno

What?...ECMAScript?

  • JavaScript is standardized
  • ECMA International
  • ECMA-262
  • The official name of JavaScript
  • ECMAScript 5 (2009), 5.1 (2011)

Good old JavaScript

Ehm...

Classes

// Constructor
function Hello(name) {
    this.name = name;
}

// Object public method
Hello.prototype.hello = function hello() {
    return 'Hello ' + this.name + '!';
};

// Static method
Hello.sayHelloAll = function () {
    return 'Hello everyone!';
};

Nice!

Well, not really

Hoisting

function foo() {
    var x = 5;


    console.log(x); // 5

    if (true) {
        // in a block
        var x = 10; // overwrites
    }

    console.log(x); // 10
    console.log(y); // undefined

    var y = 100;
}
function foo() {
    var x = 5;
    var y; // hoisted to the top

    console.log(x); // 5

    if (true) {
        // in a block
        var x = 10; // overwrites
    }

    console.log(x); // 10
    console.log(y); // undefined

    var y = 100;
}

Value of this

var obj = {
    val: 5,

    superMethod: function () {
        return this.val;
    }
};

console.log(obj.superMethod()); // 5


function logMethod(method) {
    this.val = 10;
    console.log(method()); // this points to logMethod object
}

logMethod(obj.superMethod); // 10

Modules

vs.

define('myModule', [
    'coolModule',
    'fancyModule'
], function(dep1, dep2) {
    
    // do some cool stuff

    var privateVar = "I'm private.";

    return {
        publicVar: "I'm public.",

        publicFunc: function () {
            console.log('Hello world!');
        }
    }
});
var dep1 = require('coolModule');
var dep2 = require('fancyModule');
    
// do some cool stuff

var privateVar = "I'm private.";

module.export = {
    publicVar: "I'm public.",

    publicFunc: function () {
        console.log('Hello world!');
    }
};

CommonJS

AMD

New version of JavaScript

Yeaaah!

Classes

class Shape {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    
    logInfo() {
        console.log('X: ' + this.x + ', Y: ' + this.y);
    }
}

With inheritance

class Shape {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    
    logInfo() {
        console.log('X: ' + this.x + ', Y: ' + this.y);
    }
}

class Circle extends Shape {
    constructor(x, y, radius) {
        super(x, y); // parent constructor
        this.radius = radius;
    }

    // override method
    logInfo() {
        console.log('X: ' + this.x + ', Y: ' + this.y + ', Radius: ' + this.radius);
    }
}

With static methods

class Shape {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    
    logInfo() {
        console.log('X: ' + this.x + ', Y: ' + this.y);
    }
}

class Circle extends Shape {
    constructor(x, y, radius) {
        super(x, y);
        this.radius = radius;
    }

    logInfo() {
        console.log('X: ' + this.x + ', Y: ' + this.y + ', Radius: ' + this.radius);
    }

    static hello() {
        console.log("Hello I'm a circle with a static method.");
    }
}

Arrow functions

var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
var pairs = evens.map(v => ({even: v, odd: v + 1}));
document.addEventListener('click', (event) => {
    console.log(event.target);
});

Wow, I know it from C# and Java 8

Implicit this binding

var PageHandler = {

    id: "123456",

    init: function() {
        document.addEventListener("click", (event) => {
            this.doSomething(event.type); // this points to PageHandler
        });
    },

    doSomething: function(type) {
        console.log("Handling " + type  + " for " + this.id);
    }
};

Removes confusion around value of this

Template strings

var name = "Bob"
var time = "today";

console.log(`Hello ${name}, how are you ${time}?`);
// Hello Bob, how are you today?
var count = 10;
var price = 0.25;
var message = `${count} items cost $${(count * price).toFixed(2)}.`;

console.log(message); // 10 items cost $2.50.

With calculations

Support multiline

var multiline = `Multiline
string`;

console.log(multiline); // Multiline
                        // string
var multiline = `Multiline string
                 with indentation`;

console.log(multiline); // Multiline string
                        //                  with indentation

let declarations

function getValue(condition) {

    if (condition) {
        let value = "blue";

        return value;
    } else {
        // value doesn't exist here

        return null;
    }

    // value doesn't exist here
}
if (condition) {
    console.log(value); // ReferenceError
    let value = "blue";
}

Destructuring

var colors = [ "red", [ "green", "lightgreen" ], "blue" ];

// later

var [ firstColor, [ secondColor ] ] = colors;

console.log(firstColor);  // "red"
console.log(secondColor); // "green"

Arrays

Destructuring

var options = {
    repeat: true,
    save: false
};

// later

var { repeat: localRepeat, save: localSave } = options;

console.log(localRepeat); // true
console.log(localSave);   // false

Objects

Destructuring

var options = {
    repeat: true,
    save: false
};

// later

var { repeat, save } = options;

console.log(repeat); // true
console.log(save);   // false

Objects II

Better parameters options

function f(x, y = 12) {
  // y is 12 if not passed (or passed as undefined)
  return x + y;
}

console.log(f(3)); // 15

Default parameters

Better parameters options

function f(x, ...y) {
  // y is an Array
  return x * y.length;
}
console.log(f(3, 'hello', true)); // 6

Rest parameters

Better parameters options

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

// Pass each elem of array as argument
console.log(f(...[1,2,3])) // 6

Spread operator

Better parameters options

function division({ num, divisor }) {
    return num / divisor;
}

console.log(division({ num: 5 });              // Error
console.log(division({ num: 25, divisor: 5 }); // 5

Destructured parameters

New modules syntax

import myModule from 'lib/myModule';

function doSomething() {
    myModule.someMethod();
}

export doSomething;

import, export

New modules syntax

import, export

// lib/logger.js
import textUtils from 'lib/textUtils';

export function log(message) {
    ...
    textUtils.format(message);
    ...
}

export function warn(message) {
    ...
    textUtils.format(message);
    ...
}

New modules syntax

import functions

// myModule.js
import { log, warn } from 'lib/logger';

var myModule = {
    doSomething: function () {
        
        // do cool stuff
        
        if (somethingWentWrong) {
            warn('Ooops!');
        } else {
            log("I'm here!");
        }
    }
}

export myModule;

New modules syntax

rename import

// myModule.js
import { log as myLog, warn } from 'lib/logger';

var myModule = {
    doSomething: function () {
        
        // do cool stuff
        
        if (somethingWentWrong) {
            warn('Ooops!');
        } else {
            myLog("I'm here!");
        }
    }
}

export myModule;

New modules syntax

default export

// myModule.js
import { log, warn } from 'lib/logger';

var myModule = {
    doSomething: function () {
        
        // do cool stuff
        
        if (somethingWentWrong) {
            warn('Ooops!');
        } else {
            log("I'm here!");
        }
    }
}

export default myModule;

Iterators & Generators

function createIterator(items) {
    var i = 0;

    return {
        next: function () {
            var done = (i >= items.length);
            return {
                done: done,
                value: !done ? items[i++] : undefined
            };
        }
    };
}

var iterator = createIterator([1, 2, 3]);

do {
    var progress = iterator.next();
    console.log(progress.value);
} while (!progress.done);

General pattern

Iterators & Generators

function *createIterator(items) {
    for (let i=0; i < items.length; i++) {
        yield items[i];
    }
}

let iterator = createIterator([1, 2, 3]);

console.log(iterator.next());    // { value: 1, done: false }
console.log(iterator.next());    // { value: 2, done: false }
console.log(iterator.next());    // { value: 3, done: false }
console.log(iterator.next());    // { value: undefined, done: true }

ES6 way

And much more!

  • Enhanced unicode support
  • Promises
  • Map, WeakMap
  • Set, WeakSet
  • Proxies
  • New Number, String and Math APIs
  • ...

Awesome,

I can finally develop in JavaScript

with ease!

Well...that's not absolutely true

Browser support!

...and server

We have compilers

Compile ES6 to ES5

Traceur

  • by Google
  • good ES6 support
  • features beyond ES6
    • ES7
    • annotations
    • types
  • build systems plugins
  • IDE integration

Babel

  • formely 6to5
  • better ES6 support
  • features beyond ES6
    • ES7
    • JSX (React)
  • readable code
  • build systems plugins
  • IDE integration
  • more options

What next?

ECMAScript 7?

Static types

  • TypeScript by Microsoft
  • Flow by Facebook
  • AtScript by Google

Fragmentation again?

Dark future for AtScript

Everybody agrees to collaborate

 

and align with ES7

Someday we might see static types in JavaScript

Summary

  • Cool features
  • Coming soon in browsers & on servers
  • Use it today!
  • We have compilers
  • Use it!

Resources

Marián Rusnák

ECMAScript 6

By Marian Rusnak

ECMAScript 6

Overview of the new features in ECMAScript 6 (new JavaScript version) with code examples.

  • 479
Loading comments...

More from Marian Rusnak