EcmaScript 6 features

by

JavaScript

Why

Strings (variable substitution, multi-line, tagged template strings)

Block Scoping (let, const)

Literals (octal, binary)

Rest parameters, Spread operator

Destructuring (Array, Object)

Default parameters

Lambda function / Fat Arrow (=>)

Iterators (for ...of)

Collections (Set, has(), add(), Map, set, get)

Generators (function*, yield)

Classes (class, constructor, extends, super)

Modules (export, import)

Promises (then, catch)

Proxy (meta programming)

Contents

var singleLine = `Lorem Ipsum dolore`;
console.log(singleLine);

var multiLine = `This is a text
    that spans
    multiple lines.`;
console.log(multiLine);

var a = "Alice", b = "Bob";
var interpolation = `${a} and ${b} are best friends`;
console.log(interpolation);

//Tagged template string
//example url: https://developer.mozilla.org
var a = 5;
var b = 10;

function tag(strings, ...values) {
  console.log(strings[0]); // "Hello "
  console.log(strings[1]); // " world "
  console.log(values[0]);  // 15
  console.log(values[1]);  // 50

  return "Bazinga!";
}

var v = tag`Hello ${ a + b } world ${ a * b}`;
console.log(v);

Strings (variable substitution, multi-line, tagged template strings)

// define my_fav as a constant and
// give it the value 7
const my_fav = 7;

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
}

function do_something() {
  console.log(foo); // no hoisting
  let foo = 2;
  
  var a = 5;
  var b = 10;
  if (a === 5) {
    let a = 4; // The scope is inside the if-block
    var b = 1; // The scope is inside the function

    console.log(a);  // 4
    console.log(b);  // 1
  } 

  console.log(a); // 5
  console.log(b); // 1
  
  // will print 7
  console.log(`my favorite number is: ${my_fav}`);
  
  //<compile-source>:45:3: my_fav is read-only
  //my_fav = 20;
  //console.log(`my favorite number is: ${my_fav}`);
}

varTest();
letTest();
do_something();

Block Scoping (let, const)

console.log(0b111110111 === 503); // true
console.log(0o767 === 503); // true

let foo = 0b1111;    // foo will be set to 15
let bar = 0o17;      // bar will be set to 15
console.log(`foo is ${foo} and bar is ${bar}`);

Literals (octal, binary)

function format(pattern, ...rest) {
    return rest;
}
console.log(format('a', 'b', 'c', 'd'));

let spread = ['shoulder', 'knees'];
let lyrics = ['head', ...spread, 'and', 'toes'];
console.log(lyrics);

Rest parameters, Spread operator

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

var [a, b, c] = foo;
console.log(`${a} ${b} ${c}`);

var d, e;
[d, e] = [1, 2];

function f() { return [1, 2]; }

var alice, bob;
[alice, bob] = f();
console.log(`Alice is ${alice} Bob is ${bob}`);

//object
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  

Destructuring (Array, Object)

function multiply(a, b = 1) {
  return a*b;
}

function longHand(f="foo",b="bar")
{
  return { f:f, b:b };
}

function shortHand(f="foo",b="bar")
{
  return { f, b};
}

console.log(`result: ${multiply(5)}`);
console.log(`longHand: ${longHand().f}`);
console.log(`shortHand: ${shortHand().b}`);

Default parameters

// An empty arrow function returns undefined
let empty = () => {};
console.log(empty());

// returns "foobar" 
let result = (() => "foobar")();
console.log(result);

var simple = a => a > 15 ? 15 : a; 
console.log(`result: ${simple(16)}`); // 15
console.log(`result: ${simple(10)}`); // 10

let max = (a, b) => a > b ? a : b;
console.log(`Max value: ${max(15,14)}`);

let arr = [1, 2, 3];
let squares = arr.map(x => x * x);
console.log(squares);

function Person(){
  this.age = 0;
  setTimeout(() => {
    // |this| properly refers to the person object
    this.age++; 
  }, 1000);
}
var p = new Person();
setTimeout(() => {
  	console.log(`Age: ${p.age}`);
}, 1500);

Lambda function / Fat Arrow (=>)

// Unlike for (part in thing) which iterates
// through property names of an object in a
// generic way, for (part of thing) lets the
// object decide which values it gives up on
// each iteration.
let numbers = [1,2,3];
for (let number of numbers) {
  console.log(number);
}
let numbersIterator = numbers[Symbol.iterator]();
console.log(`next val: ${numbersIterator.next().done}`);
console.log(`next val: ${numbersIterator.next().done}`);
console.log(`next val: ${numbersIterator.next().done}`);
console.log(`next val: ${numbersIterator.next().done}`);
//custom
function Words(str) {
  this._str = str;
}
Words.prototype[Symbol.iterator] = function() {
  var re = /\S+/g;
  var str = this._str;

  return {
    next: function() {
      var match = re.exec(str);
      if (match) {
        return {value: match[0], done: false};
      }
      return {value: undefined, done: true};
    }
  }
};
let helloWorld = new Words("Hello world foo bar!");
for (let word of helloWorld) {
  console.log(word);
}

Iterators (for ...of)

An iterator is an object with a next method that returns { done, value } tuples.

An iterable is an object which has an internal method, written in the current ES6 draft specs as obj[@@iterator](), that returns an iterator.

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

var gen = idMaker();

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

//infinite
function* powersOf2() {
  var i = 2;
  yield i;
  while (true) yield i *= i;
}

for (var i of powersOf2()) {
  console.log(i); //2 4 16 256
  if (i > 20) break;
}

Generators (function*, yield)

Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances. Note: *works in latest chrome and firefox

Text

// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
console.log(`set ${s.size === 2}`);//true
console.log(`set ${s.has("hello") === true}`);//true

//s.keys(), s.values(), s.entries()
for (let item of s) console.log(`set ${item}`);

// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
console.log(`map ${m.get(s) == 34}`);//true
console.log(`map ${m.size}`);//2

//m.keys(), m.values(), m.entries()
for (let [key, value] of m) {
  console.log(`${key} = ${value}`);
}

Collections (Set, has(), add(), Map, set, get)

The Map object is a simple key/value map. Any value (both objects and primitive values) may be used as either a key or a value.

The Set object lets you store unique values of any type, whether primitive values or object references.

// Superclass
class Person {
    constructor(name) {
        this.name = name;
    }

    describe() {
        return 'Person called ' + this.name;
    }
}

// Subclass
class Employee extends Person {
    constructor(name, title) {
        super(name); 
        this.title = title;
    }

    describe() {
        return super.describe() +
         ' (' + this.title + ')';
    }
}

let p = new Person('Alice');
let e = new Employee('Bob','CEO');

console.log(p.describe());
console.log(e.describe());

Classes (class, constructor, extends, super)

//how to import
import myModule from "my-module.js";
import "my-module.js" as myModule; // equivalent
import {myMember} from "my-module.js";
import {foo, bar} from "my-module.js";
import MyModule, {foo, bar} from "my-module.js";
import {reallyReallyLongModuleMemberName as shortName} from "my-module.js";
//how to export
export { generateRandom, sum }
var utils = {
  generateRandom: function() {
    return Math.random();    
  },
  sum: function(a, b) {
    return a + b;
  }
};
export default utils;//one per module
//example
// 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

Modules (export, import)

/* Promises are a library for asynchronous programming. 
Promises are a first class representation of a value that
may be made available in the future. 
Promises are used in many existing JavaScript libraries. */

function timeout(duration = 0) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, duration);
    })
}

var p = timeout(1000).then(() => {
    return timeout(2000);
}).then(() => {
    throw new Error("Houston, we have a problem");
}).catch(err => {
    return Promise.all([timeout(100), timeout(200)]);
})

/*The Promise object is used for deferred and asynchronous computations. 
A Promise is in one of these states:
pending: initial state, not fulfilled or rejected.
fulfilled: successful operation
rejected: failed operation.
settled: the Promise is either fulfilled or rejected, but not pending.*/

Promises (then, catch)

//syntax
//var p = new Proxy(target, handler);
var handler = {
    get: function(target, name){
        return name in target?
            target[name] :
            37;
    }
};
var p = new Proxy({}, handler);//target, handler
p.a = 1;
p.b = undefined;
console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37

Proxy (meta programming)

The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

handler - Placeholder object which contains traps.

traps - The methods that provide property acces. This is analogous to the concept of traps in OS.

target - Object which the proxy virtualizes. It is often used as storage backend for the proxy. Invariants (semantics that remain  regarding object non-extensibility or non-configurable properties are verified against the target.

thank you!

EcmaScript6 features by JavaScript

By ciprian chichirita

EcmaScript6 features by JavaScript

short presentation of es6 features.

  • 851