2. Rapide historique
● Créé en 1995 sous le nom de Mocha puis LiveScript
pour Mosaic HTTP Server
● Rapidement décliné en version client sous le nom de
Javascript (Sun et Netscape étaient partenaires)
● Proposé à la standardisation à ECMA International en
1996, adopté et publié en 1997 (ECMA-262)
Javascript : ES6
3. Rapide historique
● Implémentation par Microsoft sous le nom de JScript
● Quelques versions (ES2 et ES3 avec expr. régulières,
try/catch, ...) en 98 et 99
● … puis 10 ans d’hibernation avec une version 4
abandonnée ...
Javascript : ES6
4. Rapide historique
● 2009, ES5 : JSON, mode strict, reflection, etc.
● Création (2008) puis normalisation (2009) du TC39, un
comité technique formé par les principaux fabricants de
navigateurs
● ES5 est le résultat de nombreux compromis, la wishlist
des idées en cours est crée : “Harmony”
Javascript : ES6
5. Rapide historique
● 2011 : Le TC39 commence à écrire la prochaine
version
● 2011-2015 : Ecriture …
● 2015 : Publication de la première Release Candidate !
Javascript : ES6
8. Jusqu’à ES5, pas de gestion du
scope
Javascript : ES6
for (var i = 0; i < 10; i++) {
// Quelque chose.
}
console.log(i);
// => 10, i est défini dans tout le script/bloc
9. ES6 → nouvelles déclarations
Javascript : ES6
for (let i = 0; i < 10; i++) {
// Quelque chose.
}
console.log(i);
// => undefined
Les déclarations let définissent des variables dont la portée
est limité au bloc courant.
10. ES6 → nouvelles déclarations
Javascript : ES6
let i = 'bonjour';
for (let i = 0; i < 10; i++) {
console.log(i);
// 1 2 3 ... 9
}
console.log(i);
// => bonjour
Les déclarations let définissent des variables dont la portée
est limité au bloc courant.
11. ES6 → nouvelles déclarations
Javascript : ES6
const PI = 3.14;
console.log(PI);
// => 3.14
PI = 'circonférence d’un
cercle';
// Echoue de manière
silencieuse.
console.log(PI);
// => 3.14
Les déclarations const définissent constantes nommées
accessible uniquement en lecture.
// Avec un objet :
const params = { language: "JS" };
// => { language: 'JS' }
params.language = "Ruby";
// Effectue la modification (WTF?)
console.log(params);
// => { language: 'Ruby' }
params = 5;
// Echoue de manière silencieuse...
console.log(params);
// => { language: 'Ruby' }
13. La déstructuration
Javascript : ES6
La déstructuration permet de définir des variables depuis
un tableau ou un objet en utilisant une correspondance de
motif (pattern matching).
14. La déstructuration
Javascript : ES6
var mon_array = ['un', 'deux', 'trois', 'quatre'];
var [a, b, c, d] = mon_array;
console.log(a, b, c, d);
// => un, deux, trois, quatre
// => Il est possible de “zapper” un élément
var [un, , trois, quatre] = ['α', 'β', 'γ', 'δ'];
console.log(un, trois, quatre);
// => α, γ, δ
Exemple avec les tableaux :
15. La déstructuration
Javascript : ES6
var mon_object = { a: 1, b: 2, c: 3};
var { a: un, b: deux, c: trois} = mon_object;
console.log(un, deux, trois);
// => 1, 2, 3
// Marche aussi dans des objets imbriqués
var mon_object = { a: 1, b: { sous_b: 2}, c: 3};
var { a: un, b: { sous_b: deux}, c: trois} = mon_object;
console.log(un, deux, trois);
// => 1, 2, 3
Exemple avec les objets :
16. La déstructuration
Javascript : ES6
var [a, b, c] = [1, 2];
console.log(a, b, c);
// => 1, 2, undefined
var [a] = [];
console.log(a);
// => undefined
Gère les erreurs par une assignation à undefined :
17. La déstructuration
Javascript : ES6
var [a, b, c = 'Hoy !'] = [1, 2];
console.log(a, b, c);
// => 1, 2, 'Hoy !'
var {a = 'Badger !'} = [];
console.log(a);
// => 'Badger !'
… ou par une valeur par défaut spécifiée :
19. Valeurs par défaut
Javascript : ES6
function defaulted(x, y = 'foobar') {
console.log({
x: x,
y: y
});
}
defaulted();
// => { x: undefined, y: 'foobar' }
defaulted(42);
// => { x: 42, y: 'foobar' }
defaulted(42, 'es6');
// => { x: 42, y: 'es6' }
Les paramètres de fonctions peuvent avoir une valeur par
défaut en cas de non-assignation
20. Les paramètres restants
Javascript : ES6
function ma_fonction(arg1, ...leReste) {
console.log(leReste);
}
ma_fonction();
// => []
ma_fonction(1);
// => []
ma_fonction(1, 2);
// => [ 2 ]
ma_fonction(1, 2, 3, 4, 5);
// => [ 2, 3, 4, 5 ]
Les paramètres de fonctions peuvent être de nombre
variable grâce à la syntaxe ...rest
21. Les paramètres restants
Javascript : ES6
Cette syntaxe est différente par rapport au fait d’exploiter la
variable arguments comme en ES5 :
● On peut exclure les n premiers paramètres (nommés)
● ...rest est un vrai tableau, plus besoin d’utiliser
Array.prototype.slice.call(arguments) pour par exemple
utiliser les structures de boucle (forEach, etc.)
22. Les propagation de paramètres
Javascript : ES6
function ma_fonction(arg1, arg2, arg3) {
console.log(`1: ${arg1}, 2: ${arg2}, 3: ${arg3} `);
}
ma_fonction();
// => 1: undefined, 2: undefined, 3: undefined
ma_fonction('rn', 'Quizzard', 'renater');
// => 1: rn, 2: Quizzard, 3: renater
ma_fonction(...['test', 'nouveautés', 'es6']);
// => 1: test, 2: nouveautés, 3: es6
// => Equivalent ES5 :
// ma_fonction.apply(undefined, ['test', 'nouveautés', 'es6']);
Les paramètres peuvent être passés par un tableau en
utilisant une propagation (spread) :
25. Les fonctions fléchées
Exemples avec simple retour de valeur ou expression :
Javascript : ES6
// Un argument parenthèses non nécessaires
var est_pair = n => !(n % 2);
// Plusieurs arguments parenthèses nécessaires
var est_superieur = (i, j) => i > j;
console.log(est_pair(259));
// false
console.log(est_pair(-6));
// true
console.log(est_superieur(1000, 1));
// true
console.log(est_superieur(5, 5));
//false
26. Les fonctions fléchées
Exemple avec corps de fonction :
Javascript : ES6
var reverse_string = str => {
for (var i = str.length - 1, reversed = ''; i
>= 0; reversed += str[i--]) { }
return(reversed);
};
console.log(reverse_string('12345'));
// => 54321
console.log(reverse_string('Ce mec'));
// => cem eC
27. Les fonctions fléchées
Exemple avec corps de fonction et x paramètres :
Javascript : ES6
var reverse_strings = (...strings) => {
var result = '';
for (var i = strings.length - 1; i >= 0; i--) {
for (var j = strings[i].length - 1, reversed = ''; j >=
0; reversed += strings[i][j--]) { }
result += reversed;
}
return(result);
};
console.log(reverse_strings());
// => ''
console.log(reverse_strings('123', '4', '56'));
// => 654321
29. Les fonctions fléchées
Avantage #2 : Un this lexical et non local
En ES5, on rencontre souvent le “problème” de la valeur de
this non/mal assignée :
Javascript : ES6
//Methode 2 : Utiliser
Function.prototype.bind(thisArg)
function Voiture() {
this.kilometres = 100;
console.log(this.kilometres);
setTimeout((function() {
this.kilometres += 10;
console.log(this.kilometres);
}).bind(this), 2000);
}
new Voiture();
// => 100 ... 110
//Methode 1 : Utiliser une variable "self" ou "that"
function Voiture() {
var self = this;
self.kilometres = 100;
console.log(self.kilometres);
setTimeout(function() {
self.kilometres += 10;
console.log(self.kilometres);
}, 2000);
}
new Voiture();
// => 100 ... 110
30. Les fonctions fléchées
Avantage #2 : Un this lexical et non local
Les fonctions fléchées en es6 utilise un this lexical (celui du
contexte ou elles sont définies) :
Javascript : ES6
function Voiture() {
this.kilometres = 100;
console.log(this.kilometres);
setTimeout(() => {
this.kilometres += 10;
console.log(this.kilometres);
}, 2000);
}
new Voiture();
// => 100 ... 110
32. Les classes
Syntaxe :
Javascript : ES6
class NomClasse extends ClasseParent {
constructor(arguments) {
//...
}
methode(arguments) {
//...
}
get propriete() {
return ...;
}
set propriete(valeur) {
this._propriete = valeur;
}
static methodeStatique() {
//...
}
let instance = new NomClasse('foobar');
instance.methode([1, 2, 3]);
instance.propriete = 5;
NomClasse.methodeStatique();
33. Les classes
Javascript : ES6
● Gestion de l’héritage avec extends et super()
class NomClasse extends ClasseParent
● Gestion des getters et setters avec les mot-clés get et
set
get propriete() {}
● Gestion des méthodes statiques avec le mot-clé static
static method() {}
En plus d’une syntaxe plus proche de la programmation
OO, plusieurs avantages :
38. Sets
Javascript : ES6
● Valeurs uniques nativement
Améliorations notables par rapport à la gestion en array :
let set = new Set();
set.add(1)
set.size
// => 1
set.add(1)
set.size
// => 1
39. Sets
Javascript : ES6
● Recherche plus rapide / simple que .indexOf()
Améliorations notables par rapport à la gestion en array :
let set = new Set();
set.add(1)
set.has(1);
// => true
let array = [1];
array.indexOf(1) !== -1
// => true
40. Sets
Javascript : ES6
● Suppression plus rapide / simple que .filter(), etc.
Améliorations notables par rapport à la gestion en array :
let set = new Set();
set.add(1)
set.delete(1);
let array = [1];
array.filter(function(n) { return (n !== 1); });
41. Sets
Javascript : ES6
● Assurance d’itérer dans l’ordre d’ajout
Améliorations notables par rapport à la gestion en array :
let set = new Set();
set.add('a');
set.add('b');
set.add('c');
for (let x of set) {
console.log(x);
}
// => 'a', 'b', 'c', ce n’était pas forcément le cas avec ['a', 'b', 'c']
43. Maps
Javascript : ES6
● Les clés ne sont plus forcément des chaînes
Améliorations notables par rapport à la gestion en objet :
let map = new Map(), key = {};
map.set(key, 1);
map.set(NaN, 42);
map.has(key);
// => true
map.has({});
// => false : {} n’est pas === a key ! (deux objets différents)
44. Maps
Javascript : ES6
● Plus de risques de télescopage avec des propriété
natives :
Améliorations notables par rapport à la gestion en objet :
let map = new Map();
map.get('toString');
// => undefined
map.set('toString', 42);
map.get('toString');
// => true
var objet = {};
objet.toString;
// => [function()]
// On peut contourner en testant
// objet.hasOwnProperty()
objet.toString = 42;
objet.toString;
// => 42
45. WeakSet & WeakMap
Javascript : ES6
● Structure de données qui ne protège pas ses éléments
contre le ramasse-miettes (Garbage Collector)
● Le Garbage Collector supprimera des éléments quand
ils ne seront plus utilisés
● Protège contre les fuites de mémoires
46. WeakSet
Javascript : ES6
let set = new Set();
let myKey = {};
set.add(myKey);
(function() {
let myScopedKey = {};
set.add(myScopedKey);
// => set contient 2 éléments
})();
// => set contient toujours 2
éléments
let set = new WeakSet();
let myKey = {};
set.add(myKey, 'Kawai !');
(function() {
let myScopedKey = {};
set.add(myScopedKey);
// => set contient 2 éléments
})();
// => set contient 1 élément
// => Le GC a néttoyé myScopedKey
47. WeakMap
Javascript : ES6
let map = new Map();
let myKey = {};
map.set(myKey, 'Kawai !');
(function() {
let myScopedKey = {};
map.set(myScopedKey, 42);
// => map contient 2 éléments
})();
// => map contient toujours 2
éléments
let map = new WeakMap();
let myKey = {};
map.set(myKey, 'Kawai !');
(function() {
let myScopedKey = {};
map.set(myScopedKey, 42);
// => map contient 2 éléments
})();
// => map contient 1 élément
// => Le GC a néttoyé myScopedKey
48. Limitations de WeakSet &
WeakMap
Javascript : ES6
● La volatilité des structures rend impossible l’itération sur
ces objets
● .size() n’est pas disponible, dû également à la volatilité
● .clear() n’est pas disponible, c’est au GC de vider l’objet
49. Exemple : Des propriétés
“privées”
Javascript : ES6
let privates = new WeakMap();
class MaClasseBidon {
constructor(foo, bar) {
privates.set(this, { foo, bar });
}
methodeBidon() {
console.log(privates.get(this).foo);
console.log(privates.get(this).bar);
}
}
let instance = new MaClasseBidon(42,
{});
instance.methodeBidon();
// => 42, [Object]
console.log(Object.keys(instance));
// => []
51. Les symboles
Javascript : ES6
● Immuables
● Uniques
Symbol('bonjours') === Symbol('bonjours'); // => false
● Utilisés comme identifiant des propriétés d’objet
obj[Symbol('bonjours')] = 'blah blah';
let mySymbol = Symbol('bonjours');
let mySymbol2 = Symbol({});
let mySymbol3 = Symbol();
52. Les symboles
Javascript : ES6
● Permet d’éviter les conflits de noms
let toString = Symbol('toString');
let obj = {
[toString]() {
// The native toString method is not overwritten
return('Ok !');
}
};
obj.toString();
// => [object Object]
console.log(obj[toString]());
// => “Ok !”
53. Les symboles
Javascript : ES6
● Assure une “confidentialité” des propriétés
var obj = (function() {
let prop = Symbol('notYourStuff');
let returned;
returned = {
[prop] : 42
};
console.log(returned[prop]);
// Dans le scope, on peut accéder
à la propriété
return(returned);
})();
obj[prop];
// => Erreur prop n'est pas définie
// Hors du scope, on ne peut PAS
accéder à la propriété
JSON.stringify(obj);
// => {}
// La propriété est ignorée par
JSON.stringify()
56. Les itérateurs
Javascript : ES6
Lancement de l’itération
Iterable.[Symbol.iterator]()
=> Iterator
Iterator.next()
=> IteratorResult
IteratorResult.done ?
valeur =
IteratorResult.value
Fin de l’itération
Récupération d’un valeur
de l’itération
false
true
57. Les itérateurs
Javascript : ES6
let fibonacciDe10 = {
[Symbol.iterator]() {
let precedent = 0, actuel = 1, tour = 0;
return {
next() {
[precedent, actuel] = [actuel, precedent + actuel];
tour++;
return {
done: tour > 10, // false, puis true au 10ème tour
value: actuel // 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
}
}
}
}
}
59. Boucle pour itérateurs
Javascript : ES6
● Syntaxe “for…of” :
for (variable of iterator) { /*...*/ }
● Permet de “consommer” les objets itérateurs
● Itère sur les les valeurs et non les clé (for...in)
60. Boucle pour itérateurs
Javascript : ES6
for (let i of fibonacciDe10) {
console.log(i);
// 1, puis 2, 3, 5, 8, 13, 21,
// 34, 55, et enfin 89
}
61. Boucle pour itérateurs
Javascript : ES6
let monTableau = [1, 2, 3];
for (let i of monTableau) {
console.log(i);
// => 1, puis 2, puis 3
}
let monObjet = {
a: 1, b: 2, c: 3
};
for (let i of monObjet) {
console.log(i);
}
63. Les générateurs
Javascript : ES6
● Les itérateurs sont très utiles mais syntaxe complexe
● Les générateurs rendent la syntaxe plus simple
● Nouveaux mots-clés :
function* generator();
yield value;
yield* secondGenerator();
64. Les générateurs
Javascript : ES6
● Un générateur est une fonction qui retourne
automatiquement un objet Iterable
● Définis en utilisant la syntaxe function* gen() {}
● Les valeurs à retourner sont envoyées via yield
value;
68. Les promesses
Javascript : ES6
● Une promesse représente un objet dont on ne connaît
pas encore la valeur
● Nouvelle façon de gérer les opérations asynchrone
● Une promesse a 3 états possibles : en cours, puis
accomplie _ou_ rejetée
● Les états accomplie ou rejetée sont alors immuables
74. Les modules
Javascript : ES6
● Programmation modulaire permettant d’isoler des
composants dans des fichiers
● Hérite des syntaxes déjà utilisées (AMD, CommonJS)
● Modèle asynchrone, aucun code n’est exécuté tant que
le module n’est pas chargé et exécuté
75. Les modules
Javascript : ES6
// lib/malib.js
export const PI = 3.14;
export function* fibonacciDe10(){
let precedent = 0, actuel = 1, tour = 0;
while(tour < 10) {
[precedent, actuel] =
[actuel, precedent + actuel];
yield actuel;
tour++;
}
}
// index.js
import * as malib from "lib/malib";
console.log(malib.PI);
// 3.14
for(let i of malib.fibonacciDe10()) {
// 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
}
// index2.js
import PI from "lib/malib";
console.log(PI);
// 3.14
// index3.js
import {fibonacciDe10, PI} from "lib/malib";
// ...
● Syntaxe :
76. Les modules
Javascript : ES6
// lib/otherLib.js
export * from 'lib/malib';
export var maVar = 42;
// index.js
import * from 'lib/otherLib';
console.log(PI);
// 3.14
console.log(maVar);
// 42
// lib/otherLib2.js
export default function() {
console.log('Coucou');
}
var uglyLocalName = 42;
export { uglyLocalName as foo};
// index.js
import * as otherLib from 'lib/otherLib2';
otherLib.unexistantName();
// 'Coucou'
console.log(otherLib.foo);
// 42
● Délégation d’import / Default / Aliases :
78. La gestion des chaînes de
caractères
String.prototype.includes(substring, startingAt)
String.prototype.startsWith(substring, startingAt)
String.prototype.endsWith(substring, endingAt)
Javascript : ES6
79. La gestion des chaînes de
caractères
Javascript : ES6
// String.prototype.includes(substring, startingAt)
'Hello world'.includes('wor') // true
'Hello world'.includes('hell') // false, sensible à la casse
'Hello world'.includes('Hello', 1) // false, on commence à 1
// String.prototype.startsWith(substring, startingAt)
'42, born to code'.startsWith('42') // true
'42, born to code'.startsWith('foo') // false
'42, born to code'.startsWith(42, 1) // false, on commence à 1
// String.prototype.endsWith(substring, endingAt)
'42, born to code'.endsWith('code') // true
'42, born to code'.endsWith('born') // false
'42, born to code'.endsWith('code', 5) // false, on arrete à 5
// Exemple equivalent es5
String.prototype.startsWith = function(substring, startingAt) {
startingAt = (startingAt) ? startingAt : 0;
return (this.indexOf(substring) === startingAt);
};
80. La gestion des chaînes de
caractères
Gestion des gabarits de chaînes de caractères :
Javascript : ES6
`Simple chaîne`
`chaîne avec
saut de ligne au milieu`
`chaîne avec ${expression Javascript} évaluée`
fonction_tag `chaîne ou ${expression Javascript}`
81. La gestion des chaînes de
caractères
Gère les sauts de lignes nativement et protège des erreurs
de guillemets :
Javascript : ES6
// Avant on devait faire :
var old_school = "Ligne 1nLigne 2n'"";
// Swag !
let new_school = `Ligne 1
Ligne 2'"`;
82. La gestion des chaînes de
caractères
Gère les interpolation d’expressions Javascript :
Javascript : ES6
let ma_variable = "bonjours";
let ma_string = `Il y a toujours un "s" dans '${ma_variable}'`;
// => Il y a toujours un "s" dans 'bonjours'
`La variable est de type "${typeof ma_variable}"`;
// => La variable est de type "string"
`Le type de véhicule est '${vehicule.getType()}'`;
// => Le type de véhicule est 'car'
83. La gestion des chaînes de
caractères
Gère les interpolation d’expressions Javascript … mais !
Javascript : ES6
let ma_variable = 10;
console.log(`Ma variable = ${ma_variable++}`);
// => Ma variable = 10
console.log(ma_variable);
// => 11
Attention donc aux appels de méthodes, etc.
84. La gestion des chaînes de
caractères
Gestion des étiquettes (tags) pour le taint checking, par ex
:
Javascript : ES6
let a = 2;
let b = 5;
console.log(`Normalement ${ a } plus ${ b } = ${a + b}`);
// "Normalement 2 plus 5 = 7"
function tag(strings, ...values) {
console.log(strings);
console.log(values);
return "J'ai plus envie de calculer";
}
console.log(tag`Normalement ${ a } plus ${ b } = ${a + b}`);
// ['Normalement ', ' plus ', ' = ']
// [2, 3, 5]
// "J'ai plus envie de calculer"
85. Merci !
Des question ?
Pour me contacter :
linkedin.com/in/jucrouzet
github.com/jucrouzet
twitter.com/c2c