ecmascript 6 im produktivbetrieb
TRANSCRIPT
WHO AM I?
• Sebastian Springer
• aus München
• arbeite bei Mayflower
• https://github.com/sspringer82
• @basti_springer
• Consultant, Trainer, Autor
http://kangax.github.io/compat-table/es6/
Transpiler
6 → 5
Transpiler
ES6 wird noch nicht überall unterstützt, also müssen ES6-Features in ES5 übersetzt werden.
ES6 Code
class User { constructor (name) { this.name = name; } sayHello() { alert(`Hello ${this.name}`); }}
Transpiled Code"use strict"; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }var User = (function () { function User(name) { _classCallCheck(this, User); this.name = name; } _createClass(User, [{ key: "sayHello", value: function sayHello() { alert("Hello " + this.name); } }]); return User; })();
FeaturesArray comprehensions
Arrow functions Async functions
Async generator functions Classes
Class properties Computed property names
Constants Decorators
Default parameters Destructuring
Exponentiation operator For-of
Function bind
Generators Generator comprehensions
Let scoping Modules
Module export extensions Object rest/spread
Property method assignment Property name shorthand
Rest parameters React
Spread Template literals Type annotations Unicode regex
Babel
$ npm install -g babel
$ babel app.js
$ babel -o app.dist.js app.js
$ babel src -d dist
Grunt Integration$ npm install grunt grunt-babel
module.exports = function(grunt){ grunt.loadNpmTasks('grunt-babel'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.initConfig({ "babel": { options: { sourceMap: true }, dist: { files: { "dist/app.js": “app.js" } } }, "watch": { scripts: { files: [“app.js"], tasks: [“babel"] } } }); grunt.registerTask("default", ["babel"]);};
Grunt Integration
$ grunt watch Running "watch" task Waiting... >> File "app.js" changed. Running "babel:dist" (babel) task
Done, without errors.
Klassen
Manfred Jahreis / pixelio.de
Class
Syntactical Sugar, um das Prototypen-Konzept von JavaScript
Classclass Task { constructor(title) { this.title = title; this.state = 'todo'; } complete() { this.state = 'done'; } }
Class
function Task (title) { this.title = title; this.state = 'todo'; } Task.prototype.complete = function () { this.state = 'done'; };
Class - staticclass Task { ... static createTask(title) { return new Task(title); }} var task2 = Task.createTask('my2ndTask');
Class
function Task (title) { this.title = title; this.state = 'todo'; } Task.createTask = function (title) { return new Task(title);};
Class - get/setclass Task { get description() { console.log('description getter'); return this._description; } set description(val) { console.log('description setter'); this._description = val; } }
Class - inheritance
class story extends task { constructor (title, description) { this.description = description; super(title); }}
Module
URSfoto / pixelio.de
SystemJS
SystemJS
Polyfill für ES6-Module. Unterstützen import und export.
systemjs-builder: Buildsystem für Production-Build.
SystemJS - im Browser<script src="system.js"></script> <script> System.config({ baseURL: '/jsdays/es6/modules/systemjs/', transpiler: 'babel', map: { babel: 'browser.js' } }); System.import('import.js'); </script>
JSPM - SystemJS Package Manager
Paketmanager auf Basis von SystemJS. Bibliotheken können installiert und direkt verwendet werden.
$ jspm install jquery
import $ from ‘jquery’;
SystemJS - Build
$ npm install grunt grunt-systemjs-builder
System.config({ transpiler: 'babel', map: { babel: 'browser.js' } });
SystemJS - Buildmodule.exports = function(grunt){ grunt.loadNpmTasks("grunt-systemjs-builder"); grunt.initConfig({ systemjs: { options: { sfx: true, baseURL: ".", configFile: "config.js", minify: true, build: { mangle: false } }, dist: { files: [{ "src": "app/import.js", "dest": "dist/app.min.js" }] } } });};
SystemJS - Build
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script src="dist/app.min.js"></script> </body> </html>
Arrow Functionsclass List { constructor(tasks) { this.tasks = tasks; } getDone() { return this.tasks .filter(task => task.state === 'done'); }}
Arrow Functionsvar myObj = { clicked: false, init: function() { document.addEventListener('click', function() { this.clicked = true; } ); }}; myObj.init();
Arrow Functions
var myObj = { clicked: false, init: function() { document.addEventListener('click', () => { this.clicked = true; }); }}; myObj.init();
Arrow Functions
Sind an den Kontext ihrer Definition gebunden.
Arrow Functions
var myObj = { name: 'Klaus', getName: () => { return this.name; }}; console.log(myObj.getName());
var myObj = { name: 'Klaus', getFunc: function() { return () => { return this.name; } }}; var my2ndObj = { name: 'Lisa'}; var func = myObj.getFunc();console.log(func.call(my2ndObj))
Arrow Functions
Scoping
Peter Smola / pixelio.de
Scoping
Global: Variablen sind überall verfügbar. Function: Variablen sind in der aktuellen Funktion und allen
Subroutinen verfügbar. Closure: Erstellender Kontext einer Funktion und die Funktion
selbst
letVariable ist nur im aktuellen Block gültig.
Variablen werden innerhalb des Block gehoistet.
for (let task in tasks) { console.log(task);}
const
Nicht veränderliche Werte
const pi = 3.14;
Destructuring
Strukturen in einzelne Variablen zerlegen
Destructuring
var person = {name: 'Klaus', age: 42}; var {name, age} = person;
var arr = [1, 2, 3]; var [one, two, three] = arr;
var person = {name: 'Klaus', age: 42}; var {name: firstname, age} = person;
Default Parameters
Default Parameters
Jeder Parameter ohne Wert ist undefined. Möchte man das ändern, geht das im Moment nur mit einem kleinen Hack.
Früher
function testDefaults(value) { value = value || 'default'; console.log(value);} testDefaults(); // defaulttestDefaults('myValue'); // myValue
Mit ECMAScript 6
function testDefaults(value = 'default') { console.log(value);} testDefaults(); // defaulttestDefaults('myValue'); // myValue
Mit ECMAScript 6 kann man den Parametern Standardwerte zuweisen, die verwendet werden, falls kein Wert beim Aufruf
übergeben wird.
Default Parameters
Default Parameters können an jeder Stelle der Parameterliste verwendet werden.
function testDefaults(a = 'foo', b, c = 'bar') { console.log(arguments); } testDefaults(); // foo undefined bar
Default ParametersWird undefined explizit übergeben, wird trotzdem der default-
Wert benutzt.
function testDefaults(a, b = 1) { return a + b;} var b; testDefaults(2, b); // 3
Default ParametersEs können beliebige Werte verwendet werden: Primäre
Datentypen, Objekte, Arrays und Funktionsaufrufe.
function testDefaults( pri = 'hello', obj = {name: 'world'},arr = [1,2,3], funcVal = myFunc()){ console.log(pri, obj, arr, funcVal);}
Default ParametersKein Zugriff über arguments auf Default Parameters.
arguments.length wird nicht angepasst, wenn ein Default Parameter zum Einsatz kommt.
function testDefaults(a = 1) { console.log(arguments.length); console.log(arguments[0]);} testDefaults(); // 0 undefined
Default Parameters
Die Default Parameter werden zur Laufzeit ausgewertet. Es wird also bei jedem Funktionsaufruf ein neues Objekt erzeugt.
function testDefaults(arr = []) { console.log(arr); return arr;} var myArr1 = testDefaults();var myArr2 = testDefaults();
Default Parameters
Zugriff von späteren Argumenten auf frühere.
function testDefaults( arr = [1,2,3], length = arr.length) { console.log(arr); console.log(length);}
Template Strings
Helmut / pixelio.de
Template Strings
var str1 = 'Hello World'; var str2 = "Hello World"; var str3 = `Hello World`;
Template Strings
var str4 = `1 + 1 = ${1 + 1}`; console.log(str4);
Template Strings
`1 + 1 = ${1 + 1}`
“1 + 1 = “ + (1 + 1)
1 + 1 = 2
Template Strings
var str5 = `Hallo Welt!`;
Multi-Line
Taged Template Strings
function tag(string, ...values) { console.log('String:', string); console.log('Values:', values); return ‘MyString’;} tag `Hallo ${1} Welt ${2}`;
Generators
Andreas Hermsdorf / pixelio.de
Ein Generator ist eine first-class coroutine, die einen angehaltenen Ausführungskontext repräsentiert.
Generators
var gFunction = function*() { // your code in here}
var generator = gFunction();
Generator Functions
var gFunction = function*() { yield 'Hello'; yield 'World'; }
Generator
var generator = gFunction();while (true) { var current = generator.next(); if (current.done) { break; } console.log(current.value); }
Generator
generator.next(); // {value: ‘Hello’, done: false}generator.next(); // {value: ‘World’, done: false}generator.next(); // {value: undefined, done: true}generator.next(); // {value: undefined, done: true}
var gFunction = function*() { var i i = yield 'first'; i = yield 'second' + i; yield 'third' + i; } var g = gFunction();console.log(g.next());console.log(g.next(1));console.log(g.next(2));
Generator Input
Generators und for…of
var gFunction = function*() { yield 'Hello'; yield 'World'; } var generator = gFunction();for (let i of generator) { console.log(i); }
Promises
Lupo / pixelio.de
Promises
Versprechen auf die Erledigung einer asynchronen Aufgabe.
Events?
Gut für Fire and Forget, nicht aber, wenn es um Erfolg/Misserfolg geht.
Promises
• Fulfill: Aktion war erfolgreich.
• Reject: Aktion war nicht erfolgreich.
• Pending: Noch kein fulfill oder reject
• Settled: fulfilled oder rejected
Promisesvar promise = new Promise(function(resolve, reject) { if (true) { resolve("Everything is fine"); } else { reject("Something went wrong"); }});promise.then(function success(data) { console.log(data);}, function failure(err) { console.log(err);});
PromisesChaining
function async() { return new Promise(function (res, rej) { res(1); });} async().then(function (v) { return v + 1; }).then(function (v) { return v + 1; }).then(function (v) { console.log(`value: ${v + 1}`);});
(new Promise(function (res, rej) { console.log('Promise 1'); res(1); })).then(function (v) { console.log('Promise 2'); return new Promise(function (res, rej) { rej('Failed at Promise 2'); });}).then(function(v) { console.log('Promise 3'); return new Promise(function (res) { res(v + 1); })}).then(function (v) { console.log(`last Promise ${v}`)}, function (err) { console.log(`Failed: ${err}`);});
Flusssteuerung - allfunction async(number, timeout) { return new Promise(function (resolve, reject) { setTimeout(function () { console.log(`Promise Nr. ${number} resolved`); resolve(number); }, timeout); });} Promise.all([ async(1, 1000), async(2, 2000), async(3, 3000) ]).then(function (data) { console.log(`all promises resolved ${data}`);});
Flusssteuerung - all
P1
P2
P3
…
Flusssteuerung - racefunction async(number, timeout) { return new Promise(function (resolve, reject) { setTimeout(function () { console.log(`Promise Nr. ${number} resolved`); resolve(number); }, timeout); });} Promise.race([ async(1, 1000), async(2, 2000), async(3, 3000) ]).then(function (data) { console.log(`one promise resolved ${data}`);});
Flusssteuerung - all
P1
P2
P3
…
Rest
Rest
arguments ist böse!
arguments ist kein richtiges Array-Objekt
Rest Parameter steht für eine beliebige Anzahl von Argumenten.
Argumentenliste wird in ein Array umgewandelt.
Rest
function sayHello(...args) { console.log('Number of arguments: ' + args.length); } sayHello('Hallo', 'München');
Spread
CFalk / pixelio.de
Spread
Der Spread Operator kann überall eingesetzt werden, wo ein Array in eine Argumentenliste umgewandelt werden soll.
Verhält sich also ähnlich wie apply.
Spread
function sayHello(greeting, name) { console.log(`${greeting} ${name}`);} var args = ['Servus', 'München']; sayHello.apply(null, args);
Spread
function sayHello(greeting, name) { console.log(`${greeting} ${name}`);} var args = ['Servus', 'München']; sayHello(...args);
Fragen?
Rainer Sturm / pixelio.de
KONTAKT
Sebastian Springer [email protected]
Mayflower GmbH Mannhardtstr. 6 80538 München Deutschland
@basti_springer
https://github.com/sspringer82