ES6 the basics

Rok Burgar

16.3.2017

What is ES6

ECMAScript(javascript) standard

ES6 is the next version

Lots of new goodies

How to use ES6 (NOW)

Client side:

  • compile with Babel ~71%
  • rely on new browser engines
    • Chrome, Firefox, Edge, IOS 10 ~95%

Server side:

  • latest node --harmony 97%

Agenda

  1. Variables
  2. New function syntax
  3. Parameter handling
  4. Destructuring assignment
  5. Template literals
  6. Classes
  7. Promises
  8. Some other usefull functions
  9. Iterators, generator function
  10. Modules
  11. And more

1. Variables

let is the new var unless const

  • more specific, block scope = less bugs
  • no hoisting shenanigans
  • can't define them twice with the same name

1. Variables

Hoisting

  counter = 10;
  console.log(counter); // 10
  
  var counter;
  var counter;  

  counter = 10;
  console.log(counter); // 10

=

Variable declarations are moved to the top of the function scope.

  (function() {
      // limit scope with self invoked anonymous function

      var counter = 10;
      // some other code
  } ());

Limit variable scope < ES6

1. Variables

Example ES5

  var counter = 10;
  // some code here
  
  // lets use some never used variable
  for (var counter = 0; counter < 3; counter++) {
    console.log(counter); // 1, 2, 3
  }
  
  // so lets use defined var at the top here
  console.log(counter); // counter = 3
  let counter = 10;
  // some code here
  
  // lets use some never used variable
  for (let counter = 0; counter < 3; counter++) {
    console.log(counter); // 1, 2, 3
  }
  
  // so lets use defined var at the top here
  console.log(counter); // counter = 10

Example ES6

1. Variables

Always use const if you don't need let

const PI_HALF = Math.PI / 2;

// some other code
// ...

PI_HALF = 5;

function getCircumference(r) {
    return PI_HALF * r;
}

console.log(getCircumference(2));

ES5 similar: Object.defineProperty

writable, configurable

Won't protect variables that are pointers, reference to objects if we change values in them (Array, Object)

2. Short function syntax

var animalId3 = null;
list.some(function(animal) {
  var isAnimalId3 = animal.id === 3;
  if (isAnimalId3) {
    animalId3 = animal;
  }
  return isAnimalId3;
});

Happier functional programming

Also: tail recursion support!

const animalId3 = list.find((animal) => animal.id === 3);

ES6 find

< ES6

2. Short function syntax

const list = [
  {
    id : 1,
    name : "Fluffy",
    species : "dog",
    sound : "wuuuuf"
  },
  {
    id : 2,
    name : "Max",
    species : "cat",
    sound : "mijaaaw"
  },
  {
    id : 3,
    name : "Viper",
    species : "dragon",
    sound : 'graaawl'
  },
  {
    id : 4,
    name : "Kitty",
    species : "cat",
    sound : "mijaaw"
  },
  {
    id : 5,
    name : "Shadow",
    species : "dragon",
    sound : "hssss"
  }
];
const animalId3 = list.filter((animal) => animal.id === 3)[0];

const animalId3 = list.filter(animal => animal.id === 3)[0];
const animalId3 = list.filter(animal => return animal.id === 3)[0];

const animalId3 = list.filter(animal => {
  return animal.id === 3
})[0];

const animalId3 = list.filter((animal, index) => animal.id === 3)[0];
// ES5 style

var animalId3 = list.filter(function(animal) {
    return animal.id === 3; 
})[0];

ES6 style

ES5 style

3. Parameter handling

Default parameters

(x = 5) => x
function(x) {
    // x = x || 5; wrong! 0 returns 5
    x = typeof x === 'undefined' ? 5: x;
    return x;
}

Rest of parameters

function numParamsExcludinyFirstTwo(x, y, ...others) {
    return others.length;
}

Spread parameters

// spread opeartor works only on iterable objects

const names1 = ['Rok', 'Jure']
const names2 = ['Janez', 'Borut', ...names1]  // .concat
const chars = [...'Spell it']
// ["S", "p", "e", "l", "l", " ", "i", "t"] // .split("")

output(...names1); // same as output(names1[0], names1[1]);

const copy = [...names1]; // like arr.slice()

4. Desctructuring assignment

Array matching

const names = ['Rok', 'Jure']
let [name1, name2] = names
console.log(name1, name2); // 'Rok', 'Jure'

// var tmp = name1; name1 = name2; name2 = tmp
[name2, name1] = [name1, name2] 
console.log(name1, name2); // 'Jure', 'Rok'

Object matching

const person = { name : 'Rok', id : 5};
// shorthand
const { name, id } = person;

// map to variables
const { name : firstName, id : personId } = person;
console.log(firstName, personId);

In functions

function stringify([name, id]) {
    return id + ' ' + name';
}

5. Template literals

< ES6

var who = 'John';
var msg = who + 
          " is learning \n" +
          "wait for it \n" +
          "ES6";

console.log(msg);

ES6

const who = 'John';
const msg = `${who} is learning
wait for it...
ES6`;
console.log(msg);
const name = 'Tim';
const age = 20;

function createOutput(strings, nameExp, ageExp) {
  const string0 = strings[0]; // ""
  const string1 = strings[1]; // " is "
  const string2 = strings[2]; // " years old"

  return nameExp + string1 + ageExp;
}

const output = createOutput`${name} is ${age} years old`; // "Tim is 20"

Tagged

template

literals

6. Classes

Why? Pretty. I wanna be like other programming languages.

Different (yet another) class declaration.

class Shape {  
  constructor (x, y) {
    this.x = x;
    this.y = y;
  }
  move (x, y) {
    this.x = x;
    this.y = y;
  }
  toString () {
    return 'x: ' + this.x + ', y: ' + this.y;
  }
}

let shape = new Shape(10, 10);
console.log(shape.toString());

6. Classes

Inheritance, super, getter

class Rectangle extends Shape {
  constructor (x, y, width, height) {
    super(x, y)
    
    this.width = width;
    this.height = height;
  }
  get area () {
    return this.width * this.height;
  }
  toString () {
    return super.toString() + 
           ', width: ' + this.width +
           ', height: ' + this.height;
  }
}

let rectangle = new Rectangle(10, 10, 5, 5);
console.log(rectangle.toString())
console.log(rectangle.area)

7. Promises

I promise this is fun.

Why? Simpler handling of async code, function composition instead of callbacks

function getDataFromServer(id) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve({
            species : "Dog",
            sound : "wooof"
        }), 200);
    });
}

getDataFromServer(5)
.then((animal) => console.log(animal))
.catch((err) => console.log(err))
function getDataFromServer() {
    let animal = ...
    return Promise.resolve(animal);
}

7. Promises

Even more fun

function getDataFromServer(id) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve({
            species : "Dog",
            sound : "wooof"
        }), 200);
    });
}

Promise.all([
    getDataFromServer(5),
    getDataFromServer(10)
])
.then(animals => console.log(animals) )
.catch(error => console.log(error) )

Now with features like:

  • .all
  • .race
  • chaining

8. Some other usefull functions

// ARRAY
// similar to some but returns an element
Array.find
Array.findIndex
Array.keys
Array.values
Array.from

const numbers = [1, 2, 3];
numbers.includes(2); // true
// previously
numbers.indexOf(2) !== -1

// STRING
String.repeat(int)
String.startsWith(string, index)
String.endsWith(string, index)
String.includes(string, index)

// NUMBER
Number.isNaN(number)
// previously
function isNaN(number) { return number !== number; }

console.log(0.2 + 0.1 === 0.3) // false
console.log(Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON)

Math.trunc(float) // remove floating part

9. Iterators, generator function

var animals = ['lion', 'cat', 'dog'];
var iterator = animals[Symbol.iterator]();

for (let animal of animals) {
  console.log(animal);
}

// step by step
console.log(iterator.next().value); // lion
console.log(iterator.next().value); // cat
console.log(iterator.next().value); // dog

// string, set,... also has iterator support built in...
// also remember spread operator? [...iterableObj]
let fibonacci = {
    [Symbol.iterator]: function() {
        let pre = 0, cur = 1;
        return {
           next () {
               [ pre, cur ] = [ cur, pre + cur ];
               return { done: false, value: cur };
           }
        }
    }
};

for (let n of fibonacci) {
    if (n > 10)
        break;
    console.log(n);
}

Custom

iterator

From array

9. Iterators, generator function

const sequence = {};
sequence[Symbol.iterator] = function* () {
    yield 1;
    let nextId = yield 2;
    yield nextId;
};

let iterator = sequence[Symbol.iterator]();
console.log(iterator.next().value);
console.log(iterator.next().value);
console.log(iterator.next(10).value);

// 1
// 2
// 10

Custom iterator with generator function

10. Modules



//  lib/math.js
export function multiply (x, y) { return x * y }
export const pi = Math.PI

//  app.js
import * as math from "lib/math"
console.log(math.multiply(math.pi, 2 * 10))

//  anotherApp.js
import { multiply, pi } from "lib/math"
console.log(multiply(pi, 2 * 10))

// dynamic loader
// system is default loader
System.import('lib/math').then(function(math) {
    console.log(math.multiply(math.pi, 2 * 10))
});

11. And more

  • Better internationalization support
    • number format
    • currency
    • date, time
    • encoding
  • other functions
  • proxy object
  • symbols
  • creating sublass of basic objects
  • ...

Some resources

ES6 the basics - without links to solutions

By Rok Burgar

ES6 the basics - without links to solutions

Presentation of basic features from ES6, which is the new edition of standard for javascript.

  • 332