ECMAScript 2015

aka

ES2015
ES6
Harmony
ESNext
ECMA-262, 6th edition


Använd piltangenter för att växla slide
Esc för att zooma ut
Shift + Enter för att köra kod i boxar

Historik

Release År
ES1 1997
ES2 1998
ES3 1999 RegExp - ​förbättringar
try/catch
ES5 2009 Inbyggt stöd för ​JSON (stringify/parse)
Utökade metoder på Array
ES Harmony 2011 Påbörjade arbetet med ES6 som kallades ES Harmony.

Historik

Release År
ES6 2015, juni Mycket stor uppdatering (bakåtkompatibel med ES5).
Årligt release schema! ES2016, ES2017 osv.
  • Scoping
  • Moduler
  • Klasser
  • Nya objekt och nyheter i befintliga API

Show me the code!

Blockscope


function printNumbers() {
  for (var i = 0; i < 3; i++) {
    var j = i;
    console.log(j);
  }

  console.log(j);
}

printNumbers();
							

Summering blockscope

const is the new var.

Råkat skriva let? Tänk efter om du egentligen inte menade const.

Template strings

Template strings

"Template strings are enclosed by the back-tick (` `) (grave accent) character instead of double or single quotes" - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/template_strings

const user = { name: 'nils.ekman@cybercom.com '}
console.log(`Hello ${user.name}!`);

// Multiline strings
console.log(`
  Hello ${user.name}!
  Is it monday? ${new Date().getDay() === 1 ? 'yes' : 'no'}
`);
								

Tagged template strings


function format(template, expressions) {
  console.log(template, expressions);
  return template.join('');
}

// Custom format/parse
console.log(format`This is my text ${window.screen.height}!`);
							

Object literals

Object literals


// ES5
var Base64 = {
  encode: function(text) {
    return window.btoa(text);
  },

  decode: function(encoded) {
    return window.atob(encoded);
  }
};

console.log(Base64.encode('hello'));
				

Object literals - Computed property names


const key = 123;
// ES5
const MyOldObj = {};
MyOldObj['prefix' + key] = 'value'

// ES6
const MyObj = {
  ['prefix' + key]: 'value'
};

console.log(MyObj);
			

Klasser

"Klasser" i ES5


// ES5 prototypical inheritance
function Polygon(width, height) {
  this.height = height;
  this.width = width;
}

Polygon.prototype.getInfo = function() {
  return 'Height:' + this.height + ' Width:' + this.width;
};

function Square(x, y) {
  Polygon.call(this, x, y);
}

Square.prototype = Polygon.prototype;
Square.prototype.setWidth = function(width) {
  this.width = width;
  this.height = width;
};

Square.prototype.setHeight = function(height) {
  this.width = height;
  this.height = height;
};

var square = new Square(5, 5);

console.log(square.getInfo());
square.setWidth(7);

console.log(square.getInfo());
						

Klasser i ES6


// ES6 prototypical inheritance
class Polygon {
  constructor(width, height) {
    this.height = height;
    this.width = width;
  }

  getInfo() {
    return `Height: ${this.height} Width: ${this.width}`;
  }
}

class Square extends Polygon {
  constructor(width, height) {
    super(width, height);
  }

  setWidth(width) {
    this.width = width;
    this.height = width;
  }

  setHeight(height) {
    this.width = height;
    this.height = height;
  }
}

const square = new Square(5, 5);

console.log(square.getInfo());
square.setWidth(7);

console.log(square.getInfo());
						

Summering klasser

Tydligare kod

Enklare att föra resonemang kring koden

Syntaktiskt socker på "prototypical inheritance"

Default parametrar


function send(to, message = 'default message') {
  console.log('Sending message "%s" to %s', message, to);
}

send('nils.ekman@cybercom.com');
send('nils.ekman@cybercom.com', 'my message');
							

Destructing

Destructing


const { height, width } = window.screen;
console.log('h: %d, w: %d', height, width);

// Samma som:
const height = window.screen.height;
const width = window.screen.width;
							

Destructing


const { screen: { height, width } } = window;
console.log('h: %d, w: %d', height, width);
							

Destructing


var key = 'myKey';
var secret = 'mySecret';

// ES6
const result = { key, secret };

// samma sak i ES5
var result = { key: key, secret: secret };

							

Destructing


class PostHandler {
  findById(id = 1) {
    return fetch(`posts.json?id=${id}`)
      .then(res => res.json())
      .then(json => this.parsePost(json));
  }

  parsePost({ title, id }) {
    console.log(`Title = ${title}, id = ${id}`);
  }
}

new PostHandler().findById();
							

Rest parameters & spread

Rest parameters


function restParams(first, ...rest) {
  console.log(first, rest);
}

restParams('a', 'b', 'c');

							

Spread


// ES5
function toArray(obj) {
  return Array.prototype.slice.call(obj);
}
var divs = toArray(document.querySelectorAll('div'));
console.log(divs);

// ES6
const divs = [...document.querySelectorAll('div')];
console.log(divs);
							

Arrow functions

Arrow functions


// ES5
function multiply(a, b) {
  return a * b;
}

// ES6 arrow functions (implicit return)
const multiply = (a, b) => a * b;

// Block kan användas för större funktioner (explicit return)
const filterNumber = n => {
  return n > 3;
};

// Ett argument, behöver inga paranteser
const filterNumber = n => n > 3;
						

Arrow functions

Innebörden av this ändras inte med arrow functions


// ES5
var self = this;
request(url).then(function(response) {
  self.handleResponse(response);
});

// ES5
request(url).then(function(response) {
  this.handleResponse(response);
}.bind(this));

// ES6
request(url).then(response => {
  this.handleResponse(response);
});

Arrow functions


const items = [1, 2, 3];

// ES5
items.map(function(i) { return i * i; })
     .filter(function(i) { return i > 3; })
     .forEach(function(i) { console.log(i); });

// ES6
items.map(i => i * i)
     .filter(i => i > 3)
     .forEach(i => console.log(i));

	 				

Summering arrow functions

  • Bundet till rätt scope. Förhindrar att innebörden av this ändras
  • Implicit returns: const fn = () => expr;
  • Paranteser behövs om objekt ska returneras (implicit utan return):
    const fn = () => ({ expr: '1+1' });

Symbols

Ny primitiv typ i ES6.

Symbols

const mySymbol = Symbol();
console.log(typeof mySymbol);

// Unika
console.log(Symbol() === Symbol()); //false
console.log(Symbol('foo') === Symbol('foo')); //false

Symbols - som nyckel


const key = Symbol('key'), secret = Symbol('secret');

class S3Bucket {
  constructor(awsKey, awsSecret) {
    this[key] = awsKey;
    this[secret] = awsSecret;
  }

  listFiles() {
    console.log(`using key ${this[key]} and secret ${this[secret]}`);
  }
}

const bucket = new S3Bucket('myKey123', 'mySecret321');
bucket.listFiles();

Iterators

Iterators

Alla objekt kan vara itererbara

De behöver bara "implementera" en special metod, Symbol.iterator

Symbol.iterator returnerar ett objekt som har en next() metod.

Iterators


const myIterable = {
  data: [1, 2, 3],
  [Symbol.iterator]() {
    let index = 0;

    return {
      next() {
        if (index < this.data.length) {
          return {
            value: this.data[index++]
          };
        }
        return { done: true };
      }
    }
  }
};

console.log(Array.from(myIterable));

				

Iterators

Iterators = lazy


const myIterable = {

  *[Symbol.iterator]() {
    console.log(1);
    yield 1;
    yield 2;
    yield 3;
  }
};

// Drar upp hela iteratorn mha spread.
console.log([...myIterable])

					

Iterators


const myIterable = {
  counter: 1,
  [Symbol.iterator]: function* iter() {
    while(true) {
      yield this.counter++;
    }
  }
};

// Ett säkrare sätt att iterera är att använda for of
for (const n of myIterable) {
  console.log(n);
  if (n > 9) {
    break;
  }
}
					

Summering iterators

Lazy

Använd egen iterator, eller *generator

Iterera med [...spread], Array.from eller for-of

Moduler

Ett par ord om scriptladdning

Existerande tekniker för att hantera laddning av script

Glöm script-taggar direkt!

Använd AMD eller CommonJS för att hantera beroenden

Finns bra hjälpmedel för båda teknikerna, t.ex. WebPack och Browserify (för CommonJS)

a.js


export function myFunction() {}
export default {
  sayHello() {
    return 'Hello';
  }
};
							

b.js


import $ from 'jquery';
// importera hela innehållet i a.js
import myLib from './a';
							

Export / Import


// Bibliotek
import $ from 'jquery';
// Filsystem
import { elementValidation } from './lib/validation';

export default class Logger {
  constructor(el, validate = elementValidation) {
    validate(el);
    this.$el = $(el);
  }
  log(text) {
    this.$el.append(`
${text}
`); } }

Summering moduler

Tänk på SOLID-principerna även vid JS-programmering. En klass gör en sak!

Använd moduler för att importera/exportera beroenden

Flera små filer istället för få stora!

Ska jag använda ES6 idag?

JA!

Gör ditt yttersta för att undvika något äldre än ES6. Nästa år kommer ES7...

ES6 nyligen uppflyttat till status adopt av ThoughtWorks Technology Radar

Hur kan jag använda ES6 idag när webbläsarna saknar stöd?

Webbläsarstöd: https://kangax.github.io/compat-table/es6

Använd en transpiler!

Ett byggsteg som kompilerar ES6 till ES5

Demo



https://github.com/nekman/es6-vue-babel-eslint-browserify-grunt-starter

Länkar