Presented by Leon Plata

Let's Start with ES6

Support

1

Compatibility Table

Why no try?

Traspilers

io.js and node.js

Traspilers

2

let and const

3

let statement

let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope

Unlike most programming languages, JavaScript does not have block-level scope (variables scoped to surrounding curly brackets); instead, JavaScript has function-level scope. Variables declared within a function are local

Example

function varTest() {
  var x = 31;
  if (true) {
    var x = 71;  // same variable!
    console.log(x);  // 71
  }
  console.log(x);  // 71
}

function letTest() {
  let x = 31;
  if (true) {
    let x = 71;  // different variable
    console.log(x);  // 71
  }
  console.log(x);  // 31
}

for (let i = 0; i<10; i++) {
  console.log(i); // 0, 1, 2, 3, 4 ... 9
}

console.log(i); // i is not defined

const statement

This declaration creates a constant that can be global or local to the function in which it is declared. Constants are block-scoped. The value of a constant cannot change through re-assignment, and a constant cannot be re-declared. An initializer for a constant is required. A constant cannot share its name with a function or a variable in the same scope.

Example

// Assigning to A const variable is a syntax error
const A = 1; A = 2;

// const requires an initializer
const FOO; // SyntaxError: missing = in const declaration

Destructuring

4

Object Destructuring

Object destructuring assignment syntax uses an object literal on the left side of an assignment operation

Example

var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true 

// Assign new variable names
var {p: foo, q: bar} = o;

console.log(foo); // 42
console.log(bar); // true  

Array Destructuring

Similarly, you can destructure arrays using array literal syntax on the left side of an assignment operation

Example

var foo = ["one", "two", "three"];

// without destructuring
var one   = foo[0];
var two   = foo[1];
var three = foo[2];

// with destructuring
var [one, two, three] = foo;

// swapping variables
var a = 1;
var b = 3;

[a, b] = [b, a];

// Ignoring some values
function f() {
  return [1, 2, 3];
}

var [a, , b] = f();
console.log("A is " + a + " B is " + b);

Mixed Destructuring

It’s possible to mix objects and arrays together in a destructuring assignment expression using a mix of object and array literals

Example

var options = {
        repeat: true,
        save: false,
        colors: [ "red", "green", "blue" ]
    };

var { repeat, save, colors: [ firstColor, secondColor ]} = options;

console.log(repeat);            // true
console.log(save);              // false
console.log(firstColor);        // "red"
console.log(secondColor);       // "green"

Example

var metadata = {
    title: "Scratchpad",
    translations: [
       {
        locale: "de",
        localization_tags: [ ],
        last_edit: "2014-04-14T08:43:37",
        url: "/de/docs/Tools/Scratchpad",
        title: "JavaScript-Umgebung"
       }
    ],
    url: "/en-US/docs/Tools/Scratchpad"
};

var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;

console.log(englishTitle); // "Scratchpad"
console.log(localeTitle);  // "JavaScript-Umgebung"

Example

var people = [
  {
    name: "Mike Smith",
    family: {
      mother: "Jane Smith",
      father: "Harry Smith",
      sister: "Samantha Smith"
    },
    age: 35
  },
  {
    name: "Tom Jones",
    family: {
      mother: "Norah Jones",
      father: "Richard Jones",
      brother: "Howard Jones"
    },
    age: 25
  }
];

for (var {name: n, family: { father: f } } of people) {
  console.log("Name: " + n + ", Father: " + f);
}

// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"

For loop iteration

Example

function userId({id}) {
  return id;
}

function whois({displayName: displayName, fullName: {firstName: name}}){
  console.log(displayName + " is " + name);
}

var user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"

Function parameter

Function Related

5

Default parameters

// ECMAScript 5
function makeRequest(url, timeout, callback) {

    timeout = timeout || 2000;
    callback = callback || function() {};

    // the rest of the function

}

// ECMAScript 2015
function makeRequest(url, timeout = 2000, callback = function() {}) {

    // the rest of the function

}

Rest Parameters

// ECMAScript 5
function pick(object) {
    let result = Object.create(null);

    for (let i = 1, len = arguments.length; i < len; i++) {
        result[arguments[i]] = object[arguments[i]];
    }

    return result;
}

// ECMAScript 2015
function pick(object, ...keys) {
    let result = Object.create(null);

    for (let i = 0, len = keys.length; i < len; i++) {
        result[keys[i]] = object[keys[i]];
    }

    return result;
}

Allows you to specify that multiple independent arguments should be combined into an array

Spread Operator

// Normal way
let value1 = 25,
    value2 = 50;

console.log(Math.max(value1, value2));      // 50

// Better
let values = [25, 50, 75, 100]

console.log(Math.max.apply(Math, values));  // 100

// Much better
let values = [25, 50, 75, 100]

// equivalent to
// console.log(Math.max(25, 50, 75, 100));
console.log(Math.max(...values));           // 100

Allows you to specify an array that should be split and have its items passed in as separate arguments to a function

Object Related

6

Property initializer shorthand

// ECMAScript 5
function createPerson(name, age) {
    return {
        name: name,
        age: age
    };
}

// ECMAScript 2015
function createPerson(name, age) {
    return {
        name,
        age
    };
}

Method initializer shorthand

// ECMAScript 5
var person = {
    name: "Nicholas",
    sayName: function() {
        console.log(this.name);
    }
};

// ECMAScript 2015
var person = {
    name: "Nicholas",
    sayName() {
        console.log(this.name);
    }
};

Computed property names

var suffix = " name";

var person = {
    ["first" + suffix]: "Nicholas",
    ["last" + suffix]: "Zakas"
};

console.log(person["first name"]);      // "Nicholas"
console.log(person["last name"]);       // "Zakas"

Arrow Functions

7

Description

Arrow functions are, as the name suggests, functions defined with a new syntax that uses an “arrow” (=>)

// inline
var reflect = value => value;

// block
var reflect = value => {
    return value;
};

// effectively equivalent to:
var reflect = function(value) {
    return value;
};

// parenthesis
var sum = (num1, num2) => num1 + num2;

// empty
var nothing = () => {};

// return object inline
var createObj = () -> ({id: 1, value: 10});

What's the difference?

  • Lexical this binding
  • Not newable
  • Can’t change this
  • No arguments object

Lexical this binding (without)

var PageHandler = {

    id: "123456",

    init: function() {
        document.addEventListener("click", (function(event) {
            this.doSomething(event.type);     // no error
        }).bind(this), false);
    },

    doSomething: function(type) {
        var self = this;
        setTimeout(function() {
            console.log("Handling " + type  + " for " + self.id);
        });
    },

    getFirstArgFunc: function() {
        var args = arguments;
        return function() {
            return args[0];
        }
    }
};

Lexical this binding (with)

var PageHandler = {

    id: "123456",

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

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

    getFirstArgFunc: function() {
        return () => arguments[0];
    }
};

Modules

8

JavaScript Modules

  • Asynchronous Module Definition (AMD)
  • CommonJS
  • Universal Module Definition (UMD)

How modules should work

  • Module code automatically runs in strict mode and there’s no way to opt-out of strict mode.
  • Variables created in the top level of a module are not automatically added to the shared global scope. They exist only within the top-level scope of the module.
  • The value of this in the top level of a module is undefined.
  • Modules must export anything that should be available to code outside of the module.

Be careful with ES6 transpilers

ES6 transpilers compile ES6 modules to ES5. Due to the completely new way of passing on data (via bindings), you should expect the ES5 version to not always be completely compliant with the ES6 spec. Things are even trickier when transpiled ES6 code has to interoperate with native CommonJS or AMD modules.

Named Exports

//------ 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
//------ main.js ------
import * as lib from 'lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5

Importing the whole module

Default Exports

//------ myFunc.js ------
export default function () { ... };

//------ main1.js ------
import myFunc from 'myFunc';
myFunc();

Classes

9

Resctrictions

  • Class declarations, unlike function declarations, are not hoisted.
  • All code inside of class declarations runs in strict mode automatically.
  • All methods are non-enumerable.
  • Calling the class constructor without new throws an error.
  • Attempting to overwrite the class name within a class method throws an error.

Class Expression

// class expressions do not require identifiers after "class"
let PersonClass = class {

    // equivalent of the PersonType constructor
    constructor(name) {
        this.name = name;
    }

    // equivalent of PersonType.prototype.sayName
    sayName() {
        console.log(this.name);
    }
};

As argument

function createObject(classDef) {
    return new classDef();
}

let obj = createObject(class {

    sayHi() {
        console.log("Hi!");
    }
});

obj.sayHi();        // "Hi!"

Anonymous class

let person = new class {

    constructor(name) {
        this.name = name;
    }

    sayName() {
        console.log(this.name);
    }

}("Nicholas");

person.sayName();       // "Nicholas"

Accesor Properties

class CustomHTMLElement {

    constructor(element) {
        this.element = element;
    }

    get html() {
        return this.element.innerHTML;
    }

    set html(value) {
        this.element.innerHTML = value;
    }
}

Statics Members

class PersonClass {

    // equivalent of the PersonType constructor
    constructor(name) {
        this.name = name;
    }

    // equivalent of PersonType.prototype.sayName
    sayName() {
        console.log(this.name);
    }

    // equivalent of PersonType.create
    static create(name) {
        return new PersonClass(name);
    }
}

Static Properties

There is (intentionally) no direct declarative way to define either prototype data properties (other than methods) class properties, or instance property

Class properties and prototype data properties need be created outside the declaration.

Properties specified in a class definition are assigned the same attributes as if they appeared in an object literal.

class declarations to declare and define the capabilities of a class. Not its members. An ES6 class declaration defines its contract for its user.

Derived Classes

class Rectangle {
    constructor(length, width) {
        this.length = length;
        this.width = width;
    }

    getArea() {
        return this.length * this.width;
    }
}

class Square extends Rectangle {
    constructor(length) {

        // same as Rectangle.call(this, length, length)
        super(length, length);
    }
}

var square = new Square(3);

console.log(square.getArea());              // 9
console.log(square instanceof Square);      // true
console.log(square instanceof Rectangle);   // true

new.target

// abstract base class
class Shape {
    constructor() {
        if (new.target === Shape) {
            throw new Error("This class cannot be instantiated directly.")
        }
    }
}

class Rectangle extends Shape {
    constructor(length, width) {
        super();
        this.length = length;
        this.width = width;
    }
}

var x = new Shape();                // throws error

var y = new Rectangle(3, 4);        // no error
console.log(y instanceof Shape);    // true

Symbols

10

What are Symbols?

ECMAScript 6 symbols began as a way to create private object members.

 

The focus was around creating properties that were not identified by string names.

 

Any property with a string name was easy picking to access regardless of the obscurity of the name.

 

The initial “private names” feature aimed to create non-string property names. That way, normal techniques for detecting these private names wouldn’t work.

Creating Symbols

var firstName = Symbol("first name");
var lastName = Symbol();
var person = {};

person[firstName] = "Nicholas";
person[lastName] = "Zakas";

console.log("first name" in person);        // false
console.log(person[firstName]);             // "Nicholas"
console.log(firstName);                     // "Symbol(first name)"
console.log(person[lastName]);              // "Zakas"

Sharing Symbols

var uid = Symbol.for("uid");
var object = {
    [uid]: "12345"
};

console.log(object[uid]);       // "12345"
console.log(uid);               // "Symbol(uid)"

var uid2 = Symbol.for("uid");

console.log(uid === uid2);      // true
console.log(object[uid2]);      // "12345"
console.log(uid2);              // "Symbol(uid)"

Simulating private properties

var Person = (function() {
    var nameSymbol = Symbol('name');

    function Person(name) {
        this[nameSymbol] = name;
    }

    Person.prototype.getName = function() {
        return this[nameSymbol];
    };

    return Person;
}());

var p = new Person('John');
console.log('Person 3 name: ' + p.getName());
delete p.name;
console.log('Person 3 name: ' + p.getName() + ' — stays private.');
console.log('Person 3 properties: ' + Object.getOwnPropertyNames(p));

Well-known symbols

In addition to your own symbols, JavaScript has some built-in symbols which represent internal language behaviors which were not exposed to developers in ECMAScript 5 and before

Template Strings

11

Multiline Strings

let message = `Multiline
string`;

console.log(message);           // "Multiline
                                //  string"
console.log(message.length);    // 16
let message = `Multiline
               string`;

console.log(message);           // "Multiline
                                //                 string"
console.log(message.length);    // 31

Replacing

let count = 10,
    price = 0.25,
    message = `${count} items cost $${(count * price).toFixed(2)}.`;

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

Maps and Sets

12

Very quick reference

Any kind of object or primitive type can be used as key

Let's store unique values of any type of data

Map

Set

var key = {};

var map = new Map();
map.add(key, 'this is a value');
var set = new Set();
map.add(101);
map.add(101);

for (var value of set) {
  console.log(value);
} // 101 once

WeakMaps and WeakSets

13

WeakMap

The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced.  The keys must be objects and the values can be arbitrary values

new WeakMap([iterable])


// WeakMap.prototype.delete(key)
// WeakMap.prototype.get(key)
// WeakMap.prototype.has(key)
// WeakMap.prototype.set(key, value)

WeakSet

new WeakSet([iterable])


// WeakSet.prototype.add(value)
// WeakSet.prototype.delete(value)
// WeakSet.prototype.has(value)

WeakSets are collections of objects only and not of arbitrary values of any type.
The WeakSet is weak: References to objects in the collection are held weakly. If there is no other reference to an object stored in the WeakSet, they can be garbage collected.

WeakSets are not enumerable.

Iterators

14

function makeIterator(array){
    var nextIndex = 0;
    
    return {
       next: function(){
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} : {done: true};
       }
    }
}

An object is an iterator when it knows how to access items from a collection one at a time, while keeping track of its current position within that sequence

for ... of

The for...of statement creates a loop Iterating over iterable objects

let arr = [3, 5, 7];
arr.foo = "hello";

for (let i in arr) {
   console.log(i); // logs "0", "1", "2", "foo"
}

for (let i of arr) {
   console.log(i); // logs "3", "5", "7"
}

This is really just an optimization. Instead of heaving to return a full array, you can just return a generator which lazily gives individual values back at each iteration. This reduces memory and allocation. Since no array allocation is necessary, you can also express infinite data structures.

for ... of

var fibonacci = {
  [Symbol.iterator]: function*() {
    var pre = 0, cur = 1;
    for (;;) {
      var temp = pre;
      pre = cur;
      cur += temp;
      yield cur;
    }
  }
}

for (var n of fibonacci) {
  // truncate the sequence at 1000
  if (n > 1000)
    break;
  console.log(n);
}

Symbol.iterator

The Symbol.iterator well-known symbol specifies the default iterator for an object. Used by for...of.

Iterable

var myIterable = {}
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};
[...myIterable] // [1, 2, 3]

Generators

15

A generator is a special type of function that works as a factory for iterators

function* idMaker(){
  var index = 0;
  while(true)
    yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// ...

function *

yield

The yield keyword causes generator function execution to pause and the value of the expression following the yield keyword is returned to the generator's caller. It can be thought of as a generator-based version of the return keyword.

Promises

16

Very quick reference

var promise = new Promise(
    function (resolve, reject) { // (A)
        ...
        if (...) {
            resolve(value); // success
        } else {
            reject(reason); // failure
        }
    });

Thank you for your attention

References

Made with Slides.com