ECMAScript 6

En een beetje 5.1

Agenda

  • ES6 Tools
  • Opzetten grunt & browserify
  • ECMAScript 5.1 - getters + setters
  • Block-scoped variables
  • Destructuring
  • Opdracht(je)
  • Modules
  • Arrow functions
  • Opdracht(je)
  • Classes - basis
  • Opdracht!
  • Template strings
  • Subclasses
  • Zelf proberen

Transpilers

  • TypeScript
  • Traceur
  • Babel

Tools

Module systems

  • RequireJS
  • Browserify
  • webpack
  • SystemJS

Linters

  • JSLint
  • JSHint
  • JSCS
  • ESLint

Online tools

  • Codepen.io
  • jsbin
  • babel.io/repl
{
  "name": "ES6-workshop",
  "version": "6.0.0",
  "devDependencies": {
    "grunt": "~0.4.5",
    "babelify": "~6.1.3",
    "grunt-browserify": "~4.0.0",
    "grunt-contrib-watch": "~0.6.1"
  }
}

http://bit.ly/workshop-package

http://bit.ly/workshop-gruntfile

Getters & Setters

var Person = {
  firstName: 'Paul',
  lastName: 'Verbeek',

  name: function() {
    return this.firstName + ' ' + this.lastName;
  }
}

console.log(Person.name()); // Paul Verbeek
var Person = {
  firstName: 'Paul',
  lastName: 'Verbeek',

  get name() {
    return this.firstName + ' ' + this.lastName;
  }
}

console.log(Person.name); // Paul Verbeek
var Person = {
  firstName: 'Paul',
  lastName: 'Verbeek',

  name: function() {
    return this.firstName + ' ' + this.lastName;
  }
}

console.log(Person.name()); // Paul Verbeek

Person.name = 'Arjan Ceelen';

console.log(Person.name); // Arjan Ceelen

console.log(Person.firstName); // Paul
var Person = {
  firstName: 'Paul',
  lastName: 'Verbeek',

  get name() {
    return this.firstName + ' ' + this.lastName;
  }
}

console.log(Person.name); // Paul Verbeek

Person.name = 'Drewes Bos';

console.log(Person.name); // ???
var Person = {
  firstName: 'Paul',
  lastName: 'Verbeek',

  set name(fullName) {
    this.firstName = fullName.split(' ')[0];
    this.lastName = fullName.split(' ')[1];
  },

  get name() {
    return this.firstName + ' ' + this.lastName;
  }
}

console.log(Person.name); // Paul Verbeek

Person.name = 'Tom Hartwig';

console.log(Person.firstName); // Tom 
console.log(Person.name); // Tom Hartwig

http://bit.ly/es5-gsetters

Block-scoped variables

function topLevel() {
  foo = "ES";
  innerLevel();

  function innerLevel() {
    bar = 6;
  }
}

topLevel();

What will happen at runtime?

function f() {
  var foo = "ES";

  if (true) {
    var foo = 'JS';
  }

  console.log(foo);
}

f();

What will happen at runtime?

function f() {
  let foo = "ES";

  if (true) {
    let foo = 'JS';
  }

  console.log(foo);
}

f();

Block-scoping!

function f() {
  let foo = "ES";

  if (true) {
    let foo = 'JS';
  }

  let foo = 'boo!';

}

f();

Block-scoping!

function f() {
  const foo = 1;
  
  if (true) {
    const foo = 2;
  }
}

Block-scoping!

function f() {
  const foo = 1;
  
  if (true) {
    foo = 2; // nope!
  }
}

Block-scoping!

Destructuring

Constructing vs. extracting

// Single values
let jane = {};
jane.first = 'Jane';
jane.last = 'Doe';

// Multiple values
let jane = {
 first: 'Jane',
 last: 'Doe'
};
// Single values
let f = jane.first;
let l = jane.last;

// Multiple values
let ??? = jane;

Destructuring

// Single values
let jane = {};
jane.first = 'Jane';
jane.last = 'Doe';

// Multiple values
let jane = {
 first: 'Jane',
 last: 'Doe'
};
// Single values
let f = jane.first;
let l = jane.last;

// Multiple values
let { 
  first: f, 
  last: l 
} = jane;
let [x, y] = ['a', 'b'];
 // x='a', y='b'

let [x, y, ...rest] = ['a', 'b', 'c', 'd'];
 // x='a', y='b', rest = [ 'c', 'd' ]

[x,y] = [y,x]; // swap values

let [all, year, month, day] =
 /^(\d\d\d\d)-(\d\d)-(\d\d)$/
 .exec('2999-12-31');

Arrays

function getName() {
  
  $.ajax({
    dataType: "json",
    url: 'http://beta.json-generator.com/api/json/get/EkByW0sj',
    async: false,
    success: function (data) {
      console.log(data[0])
    }
  });
  
}

let {first, last, age } = getName();

http://jsbin.com/bigopetaba/

edit?js,console

Modules

// modules/math.js

// variable export
export const π = 3.14159265359;

// not exported
function power(base, exponent) {
    if (exponent > 2) {
        return base * power(base, exponent - 1);
    }
    return base * 2;
}

// exported function that uses internal function
export function square(x) {
    return power(x, 2);
}



// script.js
import { square } from './modules/math';

import { π as pi } from './modules/math';

import * as math from './modules/math';
// fooFunc.js
export default function() {}

// script.js
import fooFunc from './fooFunc.js';

Arrow functions

let arr = [1, 2, 3];
let square;

// ES5
square = arr.map(function (a) { return a * a });

// ES6
square = arr.map(a => a * a);

Less typing

function UIComponent() {
  var self = this;
  var button = document.getElementById('myButton');

  button.addEventListener('click', function () {
    console.log('CLICK');
    that.handleClick();
  });
}

UiComponent.prototype.handleClick = function () {  }; 

lexical this (niet meer self = this)

function UiComponent {
  let button = document.getElementById('myButton');
  
  button.addEventListener('click', () => {
    console.log('CLICK');
    this.handleClick();
  });
}

UiComponent.prototype.handleClick = function () {  }; 

http://bit.ly/arrow-functions

Classes

var Person = {
  firstName: 'Paul',
  lastName: 'Verbeek',

  set name(fullName) {
    this.firstName = fullName.split(' ')[0];
    this.lastName = fullName.split(' ')[1];
  },

  get name() {
    return this.firstName + ' ' + this.lastName;
  }
}
function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

Object.defineProperties(Person.prototype, {
  'name': { 
    get: function () { 
      return this.firstName + ' ' + this.lastName;
    }, 
    set: function (fullName) { 
      this.firstName = fullName.split(' ')[0];
      this.lastName = fullName.split(' ')[1];
    }
  }
});

var me = new Person('Paul', 'Verbeek');

console.log(me.name); // Paul Verbeek
class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  set name(fullName) {
    this.firstName = fullName.split(' ')[0];
    this.lastName = fullName.split(' ')[1];
  }

  get name() {
    return this.firstName + ' ' + this.lastName;
  }

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

let me = new Person('Paul', 'Verbeek');

me.log(); // Paul Verbeek

http://bit.ly/es5-classes

http://bit.ly/es6-classes

Opdracht: Carousel

http://bit.ly/es5-carousel

  • Laatste jQuery beschikbaar
  • Altijd 1 slide zichtbaar
  • Automatisch naar volgende slide (dus geen knoppen) na n milliseconde

http://bit.ly/carousel-js

Template literals

let me = {
  firstName: 'Paul',
  lastName: 'Verbeek',

  get name() {
    return `${this.firstName} ${this.lastName}`;
  }
}

console.log(Person.name); // Paul Verbeek
console.log(`Dit is
tekst over
meerdere regels`);

/* Dit is
 * tekst over
 * meerdere regels
 */

Subclasses

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  set name(fullName) {
    [this.firstName, this.lastName] = fullName.split(' ');
  }

  get name() {
    return `${this.firstName} ${this.lastName}`;
  }

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

let me = new Person('Paul', 'Verbeek');

me.log(); // Paul Verbeek
class Person {
  ...
}

class PersonWithMoreNames extends Person {
  constructor(firstName, lastName, ...otherNames) {
    super(firstName, lastName);
    this.otherNames = otherNames;
  }

  set name(fullName) {
    let names = fullName.split(' ');
    this.firstName = names.shift();
    this.lastName = names.pop();
    this.otherNames = names;
  }


  get name() {
    return 
      `${this.firstName} ${this.otherNames.join(' ')} ${this.lastName}`;
  }
}

let p = new PersonWithMoreNames('Enne', 'Ziel', 'van');

p.log(); // Enne van Ziel

http://bit.ly/es6-subclasses

En nu jullie!

ECMAScript 6 workshop

By Paul Verbeek

ECMAScript 6 workshop

  • 535