ECMAScript 2015 aka ES6
A la découverte du nouveau JavaScript
Mathieu PARISOT
Développeur Web et Java - Formateur
http://matparisot.fr
@matparisot
https://www.google.com/+ParisotMathieu
http://humantalks.com http://brownbaglunch.fr
ECMAScript = la spécification
JavaScript = une implémentation de la spécification
ECMA-262
1997 : Version 1 La version initiale
1999 : Version 3 Le JavaScript tel que vous le connaissez
2009 : Version 5 Mode strict
2011 : Version 5.1 Début de l’unification
2015 : Version 6 Harmony
A partir de la version 6 : 1 version par an
 nommage en fonction de l’année
ES2015
le renouveau du JavaScript
3 nouveautés qui vont changer votre manière de coder
Modules, classes et promesses
7 nouveautés qui vous simplifie la vie
String templates, destructuring, paramètres par défaut, fat arrow functions, block
scoping et constantes, paramètres rest et spreading
La nouveauté qui donne mal à la tête
Itérateurs et générateurs
Tous les trucs dont je n’ai pas le temps de parler en 50min 
Proxy, Map/Set, Symbol, tableaux typés et plein d’autres choses
Comment utiliser tout ça dès maintenant
Navigateurs, nodeJs, compiler vers ES5
Les modules
AMD vs Commonjs vs ES2015
1 fichier = 1 module
<script type="module" src="link/to/your/module.js"></script>
export function visible() { }
function hidden() { }
export function visible() { }
function hidden() { }
export function visible() { }
function hidden() { }
import {visible} from 'myModule';
import {visible, otherElement, andAnother}
from 'myModule';
import * as myModuleNS from 'myModule';
import {visible} from 'myModule';
import {visible, otherElement, andAnother}
from 'myModule';
import * as myModuleNS from 'myModule';
import {visible} from 'myModule';
import {visible, otherElement, andAnother}
from 'myModule';
import * as myModuleNS from 'myModule';
import {visible} from 'myModule';
import {visible, otherElement, andAnother}
from 'myModule';
import * as myModuleNS from 'myModule';
visible();
myModuleNS.visible();
export function maFonction() {};
export class maClass {};
export var maVariable = "value";
export default function () {}
Les classes
Enfin une syntaxe classique
function MyClass() {
this.attribut = '';
this.implementationMethod = function() { };
}
MyClass.prototype.inheritedMethod = function() { };
var obj = new MyClass();
obj.attribut;
obj.implementationMethod();
obj.inheritedMethod();
class ParentClass {
inheritedMethod() { }
}
class ParentClass {
inheritedMethod() { }
}
class MyClass extends ParentClass {
implementationMethod () {}
}
var obj = new MyClass();
obj.implementationMethod();
obj.inheritedMethod();
class MyClass {
constructor() {
this.attribut = '';
}
}
class MyClass extends ParentClass {
myMethod() {
super.parentAttribute = 'something';
}
}
class MyClass {
static myStaticMethod() { }
}
MyClass.myStaticMethod();
MyClass.myStaticMethod();
var obj = new MyClass();
obj.myMethod();
Tout est public
Pas d’abstraction
Sucre syntaxique
Les promesses
Simplifier le développement asynchrone
document.addEventListener('click',
function() {
console.log('someone clicked!!');
});
document.addEventListener('click', function() {
});
document.addEventListener('click', function() {
getFileName(function(filename) {
});
});
document.addEventListener('click', function() {
getFileName(function(filename) {
readFileLines(filename, function(lines) {
});
});
});
document.addEventListener('click', function() {
getFileName(function(filename) {
readFileLines(filename, function(lines) {
sendLines(lines,function(returnCode) {
});
});
});
});
document.addEventListener('click', function() {
getFileName(function(filename) {
readFileLines(filename, function(lines) {
sendLines(lines,function(returnCode) {
// on peut continuer l’exécution
// après l'envoi...
});
});
});
});
Welcome to
Callbacks HELL
Une promesse est un objet
Une promesse est un objet
avec un état
Une promesse est un objet
avec un état
En attente
Tenue
Rompue
Acquittée
var getFileNamePr = new Promise(
);
var getFileNamePr = new Promise(function(resolve,
reject) {
});
var getFileNamePr = new Promise(function(resolve,
reject) {
getFileName(function(filename) {
});
});
var getFileNamePr = new Promise(function(resolve,
reject) {
getFileName(function(filename) {
if(filename)
resolve(filename);
else
reject();
});
});
var getFileNamePr = new Promise(function(resolve,
reject) {
getFileName(function(filename) {
if(filename)
resolve(filename);
else
reject();
});
});
then()
document.addEventListener('click', function() {
getFileNamePromesse
.then(readFileLinesPromesse)
.then(sendLinesPromesse)
.then(function(returnCode) {
// On peut continuer l’exécution
// après l'envoi...
});
});
document.addEventListener('click', function() {
getFileName(function(filename) {
readFileLines(filename, function(lines) {
sendLines(lines,function(returnCode) {
// on peut continuer l’exécution
// après l'envoi...
});
});
});
});
catch()
document.addEventListener('click', function()
{
getFileNamePromesse
.then(readFileLinesPromesse)
.then(sendLinesPromesse)
.then(function(returnCode) {
// on peut continuer l’exécution
// après l'envoi...
})
.catch(function(error) {
console.log(error);
});;
});
Promise.all();
Promise.all([getValue1Promesse,
getValue2Promesse,
getValue3Promesse])
.then(function(values) {
console.log(values[0]); // value 1
console.log(values[1]); // value 2
console.log(values[2]); // value 3
});
Promise.race();
http://documentup.com/kriskowal/q/
https://github.com/petkaantonov/bluebird
String templates
La fin des concaténations ?
var helloWorld = "hello" + 'world';
var nom = 'Mathieu';
console.log('Bonjour ' + nom);
var nom = 'Mathieu';
console.log(`Bonjour ${nom}`);
var nom = 'Mathieu';
console.log(`Bonjour ${nom}`);
var nom = 'Mathieu';
console.log(`Bonjour ${nom}`);
var display = '<div class="' + classes + ' ' + classesExt + '">'
+ '<span id="' + idSp + '">' + esc(text) + '</span>'
+ '</div>';
var display = `<div class="${classes} ${classesExt}">
<span id="${idSp}">${esc(text)}</span>
</div>`;
Paramètres par défaut
function myFunction(param1, param2, param3) {
param3 = param3 || '';
// ...
}
function myFunction(param1, param2, param3) {
param3 = param3 || '';
// ...
}
function myFunction(param1,
param2,
param3 = '') {
// ...
}
function myFunction(param1,
param2 = param1,
param3) { }
function myFunction(param1,
param2 = param1,
param3) { }
MyFunction(1,2,3);
// param1=1, param2=2, param3=3
function myFunction(param1,
param2 = param1,
param3) { }
MyFunction(1,undefined,3);
// param1=1, param2=1, param3=3
function myFunction(param1,
param2 = param1,
param3) { }
MyFunction(1,2);
// param1=1, param2=2, param3=undefined
Destructuring
Simplifier l’assignation de propriétés
var myArray = ['value1', 'value2', 'value3'];
var myArray = ['value1', 'value2', 'value3'];
var val1 = myArray[0];
var val2 = myArray[1];
var val3 = myArray[2];
var myArray = ['value1', 'value2', 'value3'];
var [val1, val2, val3] = myArray;
[] {}
var myObject = {
prop1: 'value1',
prop2: 'value2',
prop3: 5,
prop4: 'ignored'
};
var myObject = {
prop1: 'value1',
prop2: 'value2',
prop3: 5,
prop4: 'ignored'
};
var {prop1, prop2, prop3} = myObject;
var myObject = {
prop1: 'value1',
prop2: 'value2',
prop3: 5,
prop4: 'ignored'
};
var {val1 : prop1,
val2 : prop2,
val3 : prop3} = myObject;
var settings = {
protocol: 'http://',
domain: 'matparisot.fr',
port: 80,
...
};
function buildUrlFromSettings(settings) {
return settings.protocol
+ settings.domain
+ ':'
+ settings.port;
}
function buildUrl({protocol, domain, port}) {
return protocol + domain + ':' + port;
}
function buildUrl({protocol = 'http://',
domain,
port = 80}) {
return `${protocol}${domain}:${port}`;
}
Fat arrow functions
Conserver le contexte dans les callbacks
['a','b','c'].filter(function(value) {
return value != 'a';
});
['a','b','c'].filter(function(value) {
return value != 'a';
});
['a','b','c'].filter(value => value != 'a');
['a','b','c'].filter(value => value != 'a');
['a','b','c'].filter(value => value != 'a');
['a','b','c'].filter(value => value != 'a');
['a','b','c'].filter(value => value != 'a');
['a','b','c'].filter((value) => {
console.log(value);
return value != 'a';
});
Size matters
function MyClass() {
this.param1 = 'value';
this.myMethod = function() {
console.log(this.param1); //'value'
setTimeout(function() {
console.log(this.param1); // undefined
},10);
};
}
function MyClass() {
this.param1 = 'value';
this.myMethod = function() {
console.log(this.param1); //'value'
setTimeout(function() {
console.log(this.param1); // undefined
},10);
};
}
function MyClass() {
this.param1 = 'value';
this.myMethod = function() {
console.log(this.param1); //'value'
setTimeout(function() {
console.log(this.param1); // undefined
},10);
};
}
function MyClass() {
this.param1 = 'value';
this.myMethod = function() {
var that = this;
console.log(this.param1); //'value'
setTimeout(function() {
console.log(that.param1); // ‘value’
},10);
};
}
function MyClass() {
this.param1 = 'value';
this.myMethod = function() {
console.log(this.param1); // 'value'
setTimeout(() => {
console.log(this.param1); // 'value'
},10);
};
}
Block Scoping
Limiter les bogues liés a l’hoisting
var myGlobale = "hello";
function myFunction() {
var param1 = "value1";
if(true) {
var param2 = "value2";
}
console.log(myGlobale);
console.log(param1);
console.log(param2);
}
var myGlobale = "hello";
function myFunction() {
var param1 = "value1";
if(true) {
var param2 = "value2";
}
console.log(myGlobale); // affiche "hello"
console.log(param1); // affiche "value1"
console.log(param2); // affiche "value2"
}
var let
var myGlobale = "hello";
function myFunction() {
var param1 = "value1";
if(true) {
let param2 = "value2";
}
console.log(myGlobale);
console.log(param1);
console.log(param2);
}
var myGlobale = "hello";
function myFunction() {
var param1 = "value1";
if(true) {
let param2 = "value2";
}
console.log(myGlobale);
console.log(param1);
console.log(param2);
}
var myGlobale = "hello";
function myFunction() {
var param1 = "value1";
if(true) {
let param2 = "value2";
}
console.log(myGlobale); // affiche "hello"
console.log(param1); // affiche "value1"
console.log(param2); // ReferenceError: param2
is not defined
}
const
Rest parameters
Paramètres infinis
...
function sum(a, b, ...values) {
var sum = a + b;
values.forEach((value) => sum += value);
return sum;
}
function sum(a, b, ...values) {
var sum = a + b;
values.forEach((value) => sum += value);
return sum;
}
sum(1,2); // 3
function sum(a, b, ...values) {
var sum = a + b;
values.forEach((value) => sum += value);
return sum;
}
sum(1,2); // 3
sum(1,2,3); // 6
function sum(a, b, ...values) {
var sum = a + b;
values.forEach((value) => sum += value);
return sum;
}
sum(1,2); // 3
sum(1,2,3); // 6
sum(1,2,3,4); // 10
var [a,b,...value] = ['a','b','c','d','e'];
console.log(a); // 'a'
console.log(b); // 'b'
console.log(values); // ['c','d','e']
Spreading
Eclatement de tableaux
...
function sum(a, b, ...values) {
var sum = a + b;
values.forEach((value) => sum += value);
return sum;
}
sum([1,2,3]); // renvoi "1,2,3undefined"
function sum(a, b, ...values) {
var sum = a + b;
values.forEach((value) => sum += value);
return sum;
}
sum(...[1,2,3]); // 6
function sum(a, b, ...values) {
var sum = a + b;
values.forEach((value) => sum += value);
return sum;
}
var myArray = [1,2,3];
sum(...myArray); // 6
Itérateurs
Parcourir des colletions
̏ Un itérateur est un objet qui permet de
parcourir tous les éléments contenus dans
un autre objet, le plus souvent un conteneur ̋
function createIntegerIterator(max) {
var curInt = 0;
return {
next: function() {
curInt++;
if(curInt <= max)
return {value: curInt, done: false};
else
return {done: true};
}
}
};
function createIntegerIterator(max) {
var curInt = 0;
return {
next: function() {
curInt++;
if(curInt <= max)
return {value: curInt, done: false};
else
return {done: true};
}
}
};
function createIntegerIterator(max) {
var curInt = 0;
return {
next: function() {
curInt++;
if(curInt <= max)
return {value: curInt, done: false};
else
return {done: true};
}
}
};
function createIntegerIterator(max) {
var curInt = 0;
return {
next: function() {
curInt++;
if(curInt <= max)
return {value: curInt, done: false};
else
return {done: true};
}
}
};
var it = createIntegerIterator(2);
console.log(it.next().value); // 1
console.log(it.next().value); // 2
console.log(it.next().done); // true
for...of
for(var item of ['a','b','c']){
console.log(item);
}
function IntergerIterable (max) {
this[Symbol.iterator] = function() {
var curInt = 0;
return {
next: function() {
curInt++;
if(curInt <= max)
return {
value: curInt,
done: false};
else
return {done: true};
}}};};
function IntergerIterable (max) {
this[Symbol.iterator] = function() {
var curInt = 0;
return {
next: function() {
curInt++;
if(curInt <= max)
return {
value: curInt,
done: false};
else
return {done: true};
}}};};
function IntergerIterable (max) {
this[Symbol.iterator] = function() {
var curInt = 0;
return {
next: function() {
curInt++;
if(curInt <= max)
return {
value: curInt,
done: false};
else
return {done: true};
}}};};
var myIterable = new IntegerIterable(2);
for(var i of myIterable) {
console.log(i);
}
Générateurs
Créer des itérateurs et bien plus
*
function* myGenerator() { }
function* myGenerator() { }
var myGenerator = function*() {};
function* myGenerator() { }
var myGenerator = function*() {};
var obj = {
gen: function*(){}
};
var iterator = myGenerator();
var iterator = myGenerator();
for(var i of iterator) {
// Faites ce que vous
// voulez de la valeur...
}
var iterator = myGenerator();
var elem = iterator.next();
if(!elem.done) {
console.log(elem.value);
}
yield
function* myGenerator()
{
yield 1;
}
function* myGenerator()
{
yield 1;
yield 2;
yield 3;
}
function* myGenerator()
{
yield 1;
yield 2;
yield 3;
}
var iterator = myGenerator();
function* myGenerator()
{
yield 1;
yield 2;
yield 3;
}
var iterator = myGenerator();
var elem = iterator.next();
elem = {
value: 1,
done: false
}
function* myGenerator()
{
yield 1;
yield 2;
yield 3;
}
var iterator = myGenerator();
var elem = iterator.next();
elem = iterator.next();
elem = {
value: 2,
done: false
}
function* myGenerator()
{
yield 1;
yield 2;
yield 3;
}
var iterator = myGenerator();
var elem = iterator.next();
elem = iterator.next();
elem = iterator.next();
elem = {
value: 3,
done: false
}
function* myGenerator()
{
yield 1;
yield 2;
yield 3;
}
var iterator = myGenerator();
var elem = iterator.next();
elem = iterator.next();
elem = iterator.next();
elem = iterator.next();
elem = {
value: undefined,
done: true
}
function IntergerIterable (max) {
this[Symbol.iterator] = function() {
var curInt = 0;
return {
next: function() {
curInt++;
if(curInt <= max)
return {
value: curInt,
done: false};
else
return {done: true};
}}};};
function* integerGenerator(max)
{
var curInt = 0;
while(curInt < max) {
curInt++;
yield curInt;
}
};
var myIterabale = integerGenerator(2);
for(var i of myIterable) {
console.log(i);
}
return & throw
function* myGenerator() {
yield 1;
yield 2;
if(checkSomething()) {
return;
}
yield 3;
}
function* myGenerator() {
yield 1;
yield 2;
if(checkSomething()) {
throw new Error('arrrrrgg');
}
yield 3;
}
next(value)
function* consoleLog() {
while(true) {
var value = yield;
console.log(`received : ${value}`);
}
}
function* consoleLog() {
while(true) {
var value = yield;
console.log(`received : ${value}`);
}
}
function* consoleLog() {
while(true) {
var value = yield;
console.log(`received : ${value}`);
}
}
function* consoleLog() {
while(true) {
var value = yield;
console.log(…);
}
}
var it = consoleLog();
function* consoleLog() {
while(true) {
var value = yield;
console.log(…);
}
}
var it = consoleLog();
it.next();
function* consoleLog() {
while(true) {
var value = yield;
console.log(…);
}
}
var it = consoleLog();
it.next();
it.next(2);
function* consoleLog() {
while(true) {
var value = yield;
console.log(…);
}
}
var it = consoleLog();
it.next();
it.next(2);
"received : 2"
function* consoleLog() {
while(true) {
var value = yield;
console.log(…);
}
}
var it = consoleLog();
it.next();
it.next(2);
"received : 2"
function* consoleLog() {
while(true) {
var value = yield;
console.log(…);
}
}
var it = consoleLog();
it.next();
it.next(2);
it.next(3);
"received : 2"
function* consoleLog() {
while(true) {
var value = yield;
console.log(…);
}
}
var it = consoleLog();
it.next();
it.next(2);
it.next(3);
"received : 3"
return(value)
throw(error)
function* integerGenerator()
{
var curInt = 0;
while(true) {
curInt++;
yield curInt;
}
}
var it = integerGenerator();
for(var i of it) {
console.log(i);
if(i >= 2) it.return();
}
Des générateurs
de générateurs…
yield*
function* gen123() {
yield 1;
yield 2;
yield 3;
}
function* gen123456() {
yield* gen123();
yield 4;
yield 5;
yield 6;
}
Et le reste
Car le chrono tourne 
Symbol()
const COLOR_RED = Symbol();
const COLOR_ORANGE = Symbol();
const COLOR_YELLOW = Symbol();
new Map()
new Set()
new WeakMap()
new WeakSet()
Uint8Array
Uint16Array
Uint32Array
Int8Array
Int16Array
Int32Array
Float32Array
Float64Array
Proxy Objects
Un objetClient
Appel
Retour
Un objetClient Proxy
var target = {};
var handler = {
get(target, propKey, receiver) {
console.log(`GET ${propKey}`);
return 123;
}
};
var proxy = new Proxy(target, handler);
var value = proxy.toto;
value = 123
Utiliser ES2015
Navigateurs, nodeJs et compatibilité
https://kangax.github.io/compat-table/es6/
63%
80%
71%
54%
53% (0.12 : 17%)
https://babeljs.io/
ES2015 ES5
$ babel script.js --out-file script-compiled.js
/**
* Hook to have ES6 in node js...
* The real stuff starts in startES6.js
*/
require("babel/register");
var startEs6 = require("./startES6");
startEs6();
La conclusion
ES5
ES2015
I
Standards
Proposer des
fondations solides
Les changements qui vont impacter votre code :
Modules
export function myFunction()
import {myFunction} from 'module'
Classes
class MyClass extends Parent {}
Promesses
var prom = new Promise(function(resolve, reject)) {}
prom.then(otherPromise);
Générateurs
function* myGenerator {
yield 'value';
}
Les changements qui vont vous simplifier la vie :
String templates
`hello ${world}`
Destructuring
var [val1,val2] = ['value1','value2'];
var {prop1,prop2} = {prop1:'value1', prop2: 'value2'};
Paramètres par défaut
function myFunction(param1, param2 = 'value') {}
Fat arrow functions
(param) => { expr; }
Les changements qui vont vous simplifier la vie :
Block scoping
let scopedVar = "value";
const scopedConst = "value";
Paramètres Rest
function myfunction(param1, ...params) {}
Spreading
...['value1','value2']
Expérimentez !
http://exploringjs.com/
http://matparisot.fr/3-nouveautes-majeurs-decmascript-2015-que-vous-allez-adorer/
http://matparisot.fr/7-nouveautes-qui-vont-vous-simplifier-la-vie-en-es-2015/
http://matparisot.fr/iterateurs-et-generateurs-avec-ecmascript-6-2015/
@matparisot - http://matparisot.fr
http://matparisot.fr/3-nouveautes-majeurs-decmascript-2015-que-vous-allez-adorer/
http://matparisot.fr/7-nouveautes-qui-vont-vous-simplifier-la-vie-en-es-2015/
http://matparisot.fr/iterateurs-et-generateurs-avec-ecmascript-6-2015/
http://humantalks.com http://brownbaglunch.fr

ECMAscript 2015 aka ES6 : à la découverte du nouveau javascript