ECMAScript 2015 – Show me the code! – Template strings



ECMAScript 2015 – Show me the code! – Template strings

0 0


es6-intro-cybercom

http://nekman.github.io/es6-intro-cybercom

On Github nekman / es6-intro-cybercom

ECMAScript 2015

aka

ES2015 ES6 Harmony ESNext ECMA-262, 6th edition

Använd piltangenter för att växla slideEsc för att zooma utShift + 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