De ES6 à ESNext

Vue d'ensemble de

JavaScript post-ES6

CC-BY-NC-4.0 / Jan. 2021 / Loïc TRUCHOT

Let / Const

  • nouveau scope: les accolades
  • nouvelle restriction: 
    • let devrait changer
    • const est figé
  • pour les objets, c'est la référence qui est constante
  • Dans le cas d'un for, let permet la "closure"
// LET && CONST
// let, const
const q = "Carbon dioxide formula?";
if (typeof q === "string") {
  var a1 = "O2"; // let a, const a
  a1 = "CO2";
}
console.log(a1);

let toto = "yo";
{
  const a2 = "H2O";
  let a3 = "Au";
  a3 = "Bo";
  console.log(a2, a3, toto);
  toto = 5;
}
console.log(toto);


const qsts = ["1+1", "2+2"];
qsts.push(6);

// qsts = [];
// console.log(a2, a3);
for (let i = 0; i < 10; i++) {
  setTimeout(function() {
    console.log(i);
  }, i * 1000);
}

Workshop

  • Ouvrir un ancien exercice
  • remplacer toutes les vars
  • trouver la règle ESLint obligeant l'usage de let et const

let it be

  • Transformer une valeur, petit à petit, en utilisant quelques variables en const ou let
    • i vaut 1
    • i augmente de 3
    • i est multiplié par 8
    • i est mis dans une liste de nombre (array)
    • on ajoute j qui vaut 40 à cette liste
    • k vaut la somme des éléments de la liste
    • on console.log le résultat

Templated string

  • règle la question de la présence de " ou de ' dans la string
  • permet d'écrire sur plusieurs lignes
  • permet de remplacer les variables entre ${...} par leurs valeurs
  • petite baisse de performance
const game = 'Mario"MO"';
const players = "Peach" 
+ ", 'Toad', Mario";
const templateString = `
<div>
  <p>"Hello ${players}. Welcome on ${game}."</p>
</div>
`;

Workshop

  • Ecrivez une fonction qui prend un Array et retourne un select (string)
  •  Ce select est composé d'options (string) dont le contenu sont les valeurs de l'Array
  • l'attribut "value" des options est un chiffre allant de 1 à n (taille de l'array)
  • Utilisez au moins une templated string contenant 2 variables
  • Bonus: au clic sur une des options, son attribut "value" est affiché dans la console

Templated strings

Arrow function

  • Le jeu des 7 différences
  • moins verbeux, plus clair pour la programmation fonctionnelle
  • fonctions anonymes
  • Plus de parenthèse, plus de return, plus de mot-cré "function"
function end (player) {
 return "Game over..." + player;
}
const end1 = function (player) {
  return "Game over..." + player;
} 
const end2 = (player) => {
  return "Game over..." + player;
}
const end3 = player => {
  return "Game over..." + player;
}
const end4 = player => "Game over..." + player;

console.log(end4("Commander Shepard"));
  • ATTENTION: le this se comporte différemment

Workshop stressant

  • Venez jusqu'au tableau écrire des arrow functions...
  • Une fonction qui prend un boolean, et qui retourne l'inverse
  • Une fonction qui double un nombre
  • Une fonction qui vérifie si un nombre est pair
  • Une fonction qui vérifie si un nombre est impair
  • Une fonction qui log tous les éléments d'un tableau
  • Une fonction qui ajoute un "s" à une string qu'on lui passe
  • Une fonction qui exécute une autre fonction qu'on lui passe et retourne le résultat de cette exécution
  • Une fonction qui additionne deux chiffre et retourner le résultat
  • Une fonction qui salue un utilisateur dans la console
  • Une fonction qui retourne toujours 42

Qui aime Harry Potter ?

  • Chaque fonction bien nommée est un pouvoir magique
  • On l'invoque en prononçant son nom, et la magie opère
  • Avada kedavra: la grenouille devient un prince.
  • Dans les débuts de l'informatique et de l'enseignement de LISP et de l'IA, il y a 60 ans, il y a eu de vraies plaintes internes pour "witchcraft" face à ce que pouvait faire les ordinateurs... (Hal Abelson, interviewé par Adam Bell)

Import / Export

  • Architecturer ses fichiers et sa pensée
  • Pas de fichier de plus de 50... à 500 lignes
  • Attention: différent sous Node.js (require)
  • export par défaut et import unique possible
  • alias possible
  • import par défaut ? DDD ?
export const balance = 10;
export const double = n => n * 2;
import { balance, double } from "./file1";
console.log(double(balance));

file1.js

file2.js

Workshop

  • Partez d'un seed parcel
  • Dans le dossier "src", creez trois sous-dossiers: "helpers", "data", "services"
  • Les helpers contiennent des fonctions génériques, réutilisables pour tous les projets.
  • Les services contiennent des fonctions d'un domaine précis
  • Les data sont les données de notre projet
  • script.js est la racine: il importe tous les exports des fichier des dossiers précédents.
  • Créez 2 fonctions très génériques, et 2 fonctions de domaines, et deux structures de données liée au domaine suivant: la musique
  • Bonus: Votre programme peut vraiment jouer de la musique avec JS

ES6 ou la nécessité d'une seed

  • rétrocompatibilité
  • usage de l'import/export
  • vivre dans le futur
  • installation de dépendances
  • linter/prettier
  • architectures automatique
  • autres outils (sass, typescript, jade, etc.)

import de dépendances du NPM

  • node -v (pour voir la version)
  • npm install -g npm (pour mettre à jour npm)
  • npm cache verify (pour obtenir les dernières versions)
  • découvrir package.json
  • npm install
  • npm install jquery
  • npm install jquery --save
  • npm install jquery ramda --save
  • npm install eslint webpack --save-dev
  • semantic versioning: major.minor.patch
import $ from 'jquery';
import { head, tail } from 'ramda';
$('body').html('coucou');
console.log(head([1, 2]));

Workshop

  • Single Page App Zen (prendre le temps), thème libre
  • dans le HTML créer un header avec 3 liens
  • ces liens permettent de montrer/cacher 3 "vues"
  • ces vues sont indépendantes les unes des autres:
    • ce sont des exports de templated-strings dans des fichier à part

 

Première SPA moderne

Bonus2 : Une des vues est un formulaire dont le contenu est envoyé avec AJAX à un site distant fictif (la requête est tentée)

Bonus1 : Le lien présentement selectionné est mis en avant

Destucturing

  • Obtenir une sous partie d'un objet...
  • ... ou d'un array
  • Très classique dans les fonctions avec un seul argument "objet"
const arr = [1, 2, 3];
const [a, b, c] = arr;
console.log(a, b, c);

const quizzSpecial = {
  name: "La cité de la peur",
  editor: "Pay2Win",
  price: 20,
  type: "Quizz"
};

const { name, editor } = quizzSpecial;
console.log(name, editor);

const checkPrice = ({ price }) => {
  console.log(price);
};

checkPrice(quizzSpecial);

Workshop

  • Créer une fonction "first", qui retourne le premier élément d'un array passé en argument
  • Créer une fonction "first2", qui retourne les deux premiers élément d'un array passé en argument, sous forme de tuple
  • Créer un objet "personne", avec nom, prénom, age
  • Créer une fonction ne gardant que le nom et le prénom, et retournant un nouvel objet les contenants
  • Bonus: Créer une fonction prenant 3 arguments: str, bgcolor, textcolor. Cette fonction retourne une div avec ces CSS et contenant ce texte. Si la textcolor n'est pas donnée, le texte est en blanc

Spread...

  • "propager"... 
  • transforme un array en une série de valeurs séparée par des virgules
  • utile avec les fonctions à arguments illimités
  • utile pour exécuter les fonctions avec un array d'arguments
  • utile pour concaténer 2 arrays
  • utile pour faire des arguments d'une fonction un array
  • est finalement une forme d'itération
Math.max(5, 6, 8, 9, 11, 999); // ?
const display3winners = (a, b, c) => {
  console.log(a, b, c);
};

const arr = [
  "Peach", 
  "Sonic", 
  "Momo54"
];
display3winners(...arr);

const arr2 = [
  "Chiffon1050", 
  "Jean louis", 
  ...arr
];
display3winners(...arr2);

function add(...nbs) {
  let total = 0;
  for (const nb of nbs) {
    total += nb;
  }
  return total;
}
console.log(add(1, 2, 3, 4));

ESNext:

Spread Objects !

  • Utiliser spread pour cloner
  • Utiliser spread pour combiner
  • Mais attention:
    • clone de surface, superficiel
    • "shallow"
  • Clone deep: via JSON, ou via récursion
export const spread = () => {
    const o1 = { toto: "titi" };
    const o2 = {...o1};
    const o3 = { 
        tutu: "tete", 
        ...o2
    };
    console.log(o1, o2, o3);

    const a1 = [1, 2, 3];
    const a2 = [...a1];
    console.log(a1, a2);

    // clone deep
    const o4 = JSON.parse(
        JSON.stringify(o3)
    );
    console.log(o4);   
}

Workshop

  • Créer une fonction "cloneDeep" utilisant un try-catch pour éviter les erreurs
  • Créer une fonction "merge" capable de combiner 2 objets

Destucturing

& Rest

  • Obtenir une sous partie d'un objet...
  • ... ou d'un array
  • La recherche n'a pas de limite, mais attention à la lisibilité
  • Très classique dans les fonctions avec un seul argument "objet"
const [a, b, ...c] = arr2;
console.log(a, b, c);

const quizzSpecial = {
  name: "La cité de la peur",
  editor: "Pay2Win",
  price: 20,
  type: "Quizz"
};
const { name, editor } = quizzSpecial;
console.log(name, editor);

const checkPrice = ({ price }) => {
  console.log(price);
};
checkPrice(quizzSpecial);

Workshop

  • Créer une fonction séparant le premier élément d'un array de tous les autres, et retourner un objet: { head: "x", tail: ["y", "z"] } si le tableau vaut ["x", "y", "z"]
  • Créer une classe "Personne", avec nom, prénom, age
  • Créer une fonction ne gardant que le nom et le prénom d'un objet issu de cette classe
  • Créer une méthode "bannir" à la classe personne, qui clone l'instance, lui ajoute "banni: true", puis log ce nouvel objet
  • Bonus: créer une fonction qui prend un nombre illimité de personnes, et nous retourne le nombre de personnes bannies

Clés calculées Clés raccourcies

  • inventés pour résoudre des cas classiques
  • calculée pour être traitée comme une variable
  • raccourcie pour être utilisée sans faire de "bruit" inutile (DRY)
// SHORT HAND KEY-VALUE
// COMPUTED KEYS
const key = "notice3";
const prix = 21;
const notice3 = {};
const divineLumiere = {
  livre: "La divine lumière",
  auteur: "Eiji Yoshikawa",
  prix,
  type: "roman",
  [key]: notice3
};
console.log(divineLumiere);

Safe navigation

& Coalescence

  • ...

ES6 classes

  • constructor
  • this
  • propriétés
  • méthodes
  • extends et super
  • new (return this)
  • ES2021: public, private, abstract, interface, overrides, etc. ?
  • Un fichier par classe ?
// classes
export class Game {
  constructor(gameName, nbPlayers) {
    this.nbPlayers = nbPlayers;
    this.gameName = gameName;
    this.editor = 'Pay2Win Corp.';
  }
  // shorthand method
  launch() {
    console.log(`${this.editor} game 
	  named ${this.gameName} will begin !`);
    // arrow function needed
    setTimeout(function() {
      console.log(this.nbPlayers + 
      	' players participate');
    }, 3000);
  }
}

export class Quizz extends Game {
  constructor(gameName, nbPlayers) {
    super(gameName, nbPlayers);
    this.type = 'Quizz';
  }
  launch() {
    super.launch();
    console.log(this.gameName + ' is a ' 
      + this.type);
  }
}

Workshop

Wack a mole...

...Orienté Objet !

On peut donner aux instances un nom et une couleur

Les instances reçoivent aussi un "top" et un "left" tirés au hasard entre 0 et 1000px

↓ Alternative... ↓

O O Games

Workshop

  • Créer une class "Magicien"
  • Un·e magicien·ne prend un nom, et un niveau entre 1 et 3
  • Instancier Harry (lvl 1), Hermione (lvl 2), et Voldemort (lvl 3)
  • Les magicien·nes ont 3 propriétés: nom, niveau, pointsDeVie (10 au départ)
  • Les magicien·nes ont 2 méthodes: endoloris (fait perdre 3pv à une cible prise en argument) et avadaKedavra (tue une cible prise en argument)
  • Seul·es les magicien·nes de lvl 2 ou + peuvent utiliser la seconde
  • Toutes les interaction s'affichent dans la console, dont la mort

Avada kedavra

A la fin, Voldemort et Harry meurent, Hermione survit avec 4 pdv

Bonus: Harry ne peut pas mourir car il est immunisé à Avada Kedavra

Bonus 2: ce  combat épique se passe dans des setTimeouts

Deux nouveaux « C » à retenir

 

Controler this

old fashioned functions: function () {}

VS  Arrow functions: =>

Récursion

La récursion, niveau expert 

  • map ou filter de "head" en "tail"
  • une liste, dans une liste, dans une liste, ... ?

D.D.D.

pour Domain Driven Design

images ? vidéo ? vétérinaire ? 

nourriture ? medecine ? aviation ? fleurs ?

 

Anthropologie et analyse des métiers

un petit mot a propos de

Workshop

Projet pro: Roulette !

JQuery autorisé et encouragé

Workshop

 

  • Design: la wireframe
  • User stories sur Trello
  • Poker agile noté en fibonacci points

Workshop

 

  • DDD: analyser le domaine
  • commencer avec une seed, choisir outils et dépendances
  • Enfin écrire le code (et trouver des bouts de code css / js en ligne ?)

Workshop

Rétrospective agile !

  • Livrer le projet sur github, avec un README.md décent
  • mise en ligne du site statique (pages github)

puis...

Les belles Promesses

ou la gestion de l'asynchrone en JavaScript

Plusieurs noms, un seul usage

  • Promise, Future, Delay, Deferred, Async
  • Opérer des calculs/transformations/effets avec une valeur qui n'est pas encore disponible !
  • SetTimeout, Ajax, base de données, animations
  • Énormément de fonctions de librairies retournent des promesses: on les reconnaît grâce au ".then()"

Workshop

  • Trouver une API gratuite en JSON
  • Partager sur slack
  • Installer axios
  • Interroger une API avec un "get"
  • Traiter le résultat avec un "then"

Une nouvelle promesse

const end = new Promise((resolve, reject) => {
  console.log('Game over...');
  setTimeout(() => {
      resolve('... try again ?');
  }, 1000);
});

end.then((val) => console.log(val));
  • La promesse est un objet, avec une méthode .then()
  • Resolve désigne ce qui déclenchera le "then"... et avec quelle valeur !
  • La promesse répond à un besoin: brancher conceptuellement le "return" d'une fonction mère à une fonction fille

Workshop

  • Ecrire 4 setTimeouts imbriqués, qui font un console.log de 3, 2, 1, "bonne année !" à 1 secondes d'intervalle l'un de l'autre 
  • Ecrire une fonction "delay" retournant une promesse, et contenant un setTimeout resolvant une data et utilisant un timer, passés en argument de "delay"
  • Corrigez le code de "bonne année" avec vos "delay"

Le "callback hell"

et le code "spagetthi" 

Promesse non tenue

  • On peut choisir quand s'exécute l'erreur, en utilisant le reject ou lorsqu'une erreur est "throw"
  • On subit parfois ce reject depuis une promesse qu'on ne contrôle pas. On utilise:
    • .catch()  à la fin des .then
    • ou bien la seconde fonction passée en param du .then
var promise1 = new Promise(function(resolve, reject) {
  throw new Error("Oh mon dieu, il y a eu un bug !");
});

promise1.catch(function(error) {
  console.error(error);
});

Le "reject" et le "catch"

  • L'avantage d'un reject est qu'il permet de bypasser la suite de la chaîne de «then"
import { get } from "axios";

function pileOuFace() {
  return new Promise((resolve, reject) => {
    if (Math.random() > 0.5) {
      resolve("Réussite");
    } else {
      reject("Échec");
    }
  })
}
pileOuFace()
  .then(() => get("https://toto.com/api/cadeau"))
  .then((cadeau) => mail(cadeau))	
  .catch(msg => console.log(msg));

AJAX sans bibliothèque

  • Commenter ce code ligne par ligne
  • Comment enchainer plusieurs requêtes ?
  • Ou placer la promesse ?
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts/1");
xhr.onload = () => console.log(xhr.responseText);
xhr.onerror = () => console.error(xhr.statusText);
xhr.send();

W3C fetch implementation ?

  • Différence ESx et W3C ?
  • Une implémentation critiquée
  • D'où l'usage de jquery, axios, bluebird (ou un service dédié dans angular), par ex.
fetch('https://api.github.com/users/ltruchot')
  .then(response => response.json())
  .then(data => {
    console.log(data);
  })
  .catch(error => console.error(error))

Workshop

  • Utilisez "fetch" pour interroger un serveur distant
  • Sur https://jsonplaceholder.typicode.com/posts
    • filtrer tous les articles dont le titre contient "dolorem"
    • Bonus: affichez les convenablement dans des div, avec h3 et p

Async / Await

  • Dans une fonction "async", les instruction "await" sont attendues
  • Attention: ES7, nécessite babel ou typescript
  • Risque de retour du callback hell: utiliser avec prudence
async function welcomePlayer(playerName) {
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log(`La partie commence, ${playerName} !`);
  const data = await fetch("https://jsonplaceholder.typicode.com/posts")
  	.then(res => res.json());
  return data;
}
welcomePlayer("Peach");
const data = welcomePlayer("Mario").then(console.log);
  • Hors de la fonction, le code reste simultané
  • le "return" retourne une promesse
  • côté obscur: plus séduisant, mais finalement moins "scalable" (ex: reduce de promesses)

Workshop

Event loop

Quart d'heure TV chill

Promise.all

  • Une méthodes statique de la pseudo-classe «Promise»
  • Une seule promesse pour les contrôler toutes...
  • Prend une liste ordonnée de promesses ,
  • Retourne une liste de valeurs, dans le même ordre
import { get } from 'axios';

Promise.all([
  get('http://localhost:3000/articles'),
  get('http://localhost:3000/users'),
]).then((arr) => {
  console.log(arr[0].data)
  console.log(arr[1].data);
});

Workshop

  • Obtenez votre accompte github et celui d'un autre, dans un Promise.all
  • Présentez les dans une ul/li
  • Ex: https://api.github.com/users/ltruchot
  • Bonus: 3 amis + mappez sur les avatars, et présentez les dans des bulles 

Live coding

Un serveur en node.js

Et ses fichiers JSON

Workshop

  • Liste -> Fiche, l'alpha et l'omega du web professionnel
  • Choisir un theme
    • créer un fichier db.json pour json-server
    • list: collection d'objet id + nom
  • Dans un accordéon jquery, présenter cette liste
  • Au click, faites une requête AJAX pour aller chercher la fiche correspondante:
    • all: collection d'objets plus complets avec des ids
  • Bonus: un "loader" doit être visible pendant les requêtes AJAX (ralentissez le réseau dans chrome)

Le constructeur Set

const lastPlayers = new Set([
  "Toad",
  "Wario"
]);
lastPlayers.add("Wario");
console.log(lastPlayers);
lastPlayers.delete("Toad");
console.log(lastPlayers);

Workshop

  • Créer une fonction nommée "unique"
  • Elle prend un array et retourne un array
  • Elle retire tous les doublons de cet array
  • Usage de Set obligatoire
  • Utilisez google pour combler vos manques
  • Bonus: Est-ce que plusieurs objets ayant les mêmes clés valeur sont considéré comme des doublons ? Si non, faire en sorte que oui

Set

Le constructeur Map

const lastPlayer = new Map([
  ["name", "Luigi"]
]);
console.log(lastPlayer);
lastPlayer.set("age", 45);
console.log(lastPlayer);
lastPlayer.forEach(a => 
  console.log(a));
console.log(
  lastPlayer.has("age"),
  lastPlayer.has("test"),
  lastPlayer.get("name")
);

Appendice 1

filter, map, reduce

  • La sainte trinité de la programmation fonctionnelle
  • Prennent des fonctions à appliquer à chaque élément d'une liste
  • Retournent de nouvelles listes, "immutables en surface"
  • Couvrent 80% des problèmes que nous devons résoudres en informatique
  • Higher Order Functions: fonctions avec callbacks...
    • Déclarées, non exécutées !
    • Les exécuteront toutes seules, au bon moment
  • En fait, opérations sur des structures définies en théorie des catégories (Ex: Semi-Groupes, Monoïdes, Monades, Functors...) 
  • https://mostly-adequate.gitbooks.io/mostly-adequate-guide/

Filter

le bras poubelle

Workshop

  • Augmenter la liste avec hommes et femmes
  • Garder les hommes
  • Garder les vieux hommes
  • garder les vieux hommes qui aiment cuisiner
const users = [
  {
    prenom: 'Étienne',
    age: 42,
    sexe: 'M',
    hobbies: ['videogames', 'cooking'],
  }
 ];

Filter

  • Débat et Live coding: un exemple de donnée filtrable ?
  • Utilisez le "filter" de ramda, dans un "pipe"

Map

le bras actif

Workshop

Map

  • Reprenez votre liste d'users
  • Produisez une liste ne gardant que les prénoms et hobbies
  • Produisez une liste contenant des paragraphes HTML :
    • "<prenom> aime <hobby1>, <hobby2>, <hobby3>" pour chaque user.
  • Produisez une liste filtrant les hommes aimant le sport, et transformez les en une div qui les décrits
  • Mettez ces divs  dans le DOM
  • Utilisez le "map" et le "filter" de ramda, dans un "pipe" pour faire la même
  • Bonus: faire d'une liste d'url une liste de promesses, avec "get"
    • Comment attendre qu'elle finissent toutes ? Comment faire une opération lorsqu'elles sont toutes finies, même si une bug

Reduce

Le bras multiusage

  • Est une méthode d'Array
  • Plusieurs nom: Fold, Aggregate, Reduce
  • Est "immutable en surface": retourne une valeur liée à un cumul d'autres valeur
  • Prend une fonction et un accumulateur en argument
  • cette fonction sera executée successivement sur chaque éléments de la liste: ses arguments sont
    • l'accumulateur
    • l'élément courant
  • Elle doit retourner l'accumulateur, prêt pour la prochaine fonction
  • L'alpha et l'omega des méthodes de listes

Reduce

 

  • C'est mathématique
  • En théorie des catégories, la structure la plus utilisée est le monoïde.
  • Un monoïde un ensemble possédant
    • un « append » (ou loi de composition associative)
    • une identité (ou élément neutre)
  • Exemples:
    • l'addition, ensemble entiers, opération +, identité 0
    • la multiplication, ensemble entiers, opération *, identité 1
    • Autres exemples ?
  • En fait, les monoïdes sont partout, les collections sont des ensembles
  • Reduce représente le cumul de 0 à n valeurs, avec un élément neutre comme accumulateur d'origine

Pourquoi reduce est la plus importantes des méthodes de JavaScript ?

Reduce

 

Exemples

// la somme 
[1,2,3].reduce((a, b) => a + b); // 6
[].reduce((a, b) => a + b); // ???
[].reduce((a, b) => a + b, 0); // 0

// la multiplication
[1,2,3].reduce((a, b) => a * b); // 6
[1,2,3].reduce((a, b) => a * b, 0); // ???
[].reduce((a, b) => a * b, 1); // 
  • donc fold !== reduce (pas de fold en JS, malheureusement)
  • Il existe aussi un "reduceRight"

Workshop

Reduce

  • Calculer la moyenne des ages de la classe grâce à un reduce
  • Faire un reduce concaténant les prénoms de la classe, en une string qui nous salue tous
  • Prouver que filter peut-être fait avec un reduce
  • Prouver que map peut-être fait avec un reduce
  • Prouver que max peut-être fait avec un reduce
  • Utilisen le reduce de ramda pour faire "sum" et un "mul"
  • Bonus: faire un reduce de "get" de axios, chaînés par des ".then"

Workshop

Reduce

  • Faites un "reduceRight" pour additionner un tableau de nombre
  • Faites un "reduceRight" pour additionner un tableau de string, contenant les mots ["le" , "petit", "chat"]
  • Qu'en concluez vous, mathématiquement parlant ?
  • Faire un reduce de AND
  • Faire un reduce de OR
  • Bonus: Réécrire le Array.join avec un reduce

Workshop

map-filter-reduce

  • Ecrivez vos propres fonctions :
    • map, sans Array.map, ni Array.reduce
    • filter, sans Array.filter, ni Array.reduce
    • reduce, sans Array.reduce

Serious gaming

Coder le programme d'un ascenseur

 

https://play.elevatorsaga.com/

Appendice 2: pipe, compose

  • Un "pipeline" de fonctions, ou "chaîne" de fonctions
  • Chaque fonction prendra en input l'output de la précédente
  • Le pipe retourne cette nouvelle fonction, faites des autres, prête à prendre une valeur en entrée
  • C'est donc une fonction composée de plusieurs fonctions
  • Bonne pratique:
    • chaque fonction devrait prendre/retourner le même type
    • n'avoir qu'argument
    • sauf éventuellement à la fin du pipeline

Exemple théorique

 

import { map, reduce, pipe, prop } from 'ramda';

const double = a => a * 2;
const x4 = pipe(double, double);
console.log(x4(100));

const arr = [{ name: 'Samir', age: 24 }, { name: 'Gaël', age: 55 }];
const getAge = map(prop('age')); // pluck
const sum = reduce((a, b) => a + b, 0); // sum
const divide = divider => nb => nb / divider; // divide
const ageAverage = pipe(getAge, sum, divide(arr.length)); // ou converge/lift

console.log(ageAverage(arr));
  • Un « pipe » officiel est en cours de formalisation pour ESNext
  • Enfin, le "compose"... juste un «pipe» inversé !
  • Pourquoi existe-t-il alors ?

Live coding

Comment coder notre propre « pipe » ou « compose »

  • Pour 2 fonctions ?
  • Pour un nombre illimité de fonctions ?

Workshop

const vetements = [
  {nom: "chemise", taille: "L"}, 
  {nom: "chemise", taille: "XL"}, 
  {nom: "chemise", taille: "XL"}, 
  {nom: "chemise", taille: "S"},
  {nom: "jean", taille: "S"},
  {nom: "jean", taille: "M"},
];

functional pipelines

  • Voici le stock de vêtement restant pour les soldes
  • On veut prévenir nos clients des tailles restantes de chemises
  • On a donc besoin d'un array final valant: 
  • Usage du pipe obligatoire, avec l'array comme argument final
["L", "XL", "S"]
  • Bonus: une dernière opération devrait ordonner les tailles de XXS à XXL

Quand le Code (re)devient Math

pipe(map(prop("length")), map(even)) === map(pipe(prop("length")), even))

Appendice 3: fantasy land

Appendice 4: prototype

  • La seule vraie mécanique d'héritage en JS
  • Des propriétés et méthodes cachées pour chaque variables (Boxing) 
  • Permet de mutualiser certaines fonctionnalités
  • Permet de librement s'inspirer d'un objet pour en créer un autre
const animal = {
  categorie: 'animal',
  son: 'grogne',
  dormir() {
    console.log('ZZZzzzzzZZZ');
  },
  parler() {
    console.log(this.son);
  },
};
animal.parler();
const chat = Object.create(animal, { son: { value: 'miaou' } });
chat.dormir();
chat.parler();

Listes, objets et lodash

  • ancêtre et concurrent de Ramda
  • parfait pour faire toutes sortes d'opération sur les listes et les Array, sans ré-inventer la roue
  • _ est son prefix (objet global) 
  • fork d'underscore, plus complet, mieux en front

Exercice collectif:

  • choisissez une fonctionnalité de lodash
  • faire votre propre exemple
  • l'expliquer aux autres
  • Bonus: explique « chain »

Date et moment.js

  • La gestion des dates en JS (en tout) est très complexe
  • Formattage, additions, comparaisons....
  • moment est une librairie spécialisée
  • la fonction "moment" sert de wrapper pour manipuler les dates

Exercice collectif:

  • choisissez une fonctionnalité de moment.js
  • faire votre propre exemple
  • l'expliquer aux autres

fonctionnel et ramda

  • Lispisation de JavaScript:
    • rendre les principales méthodes d'Array  first class
    • rendre les principales opérations first class
    • rendre les principales structures de contrôle first class
    • immutable, autocurryfié, pipeable

Exercice collectif:

  • choisissez une fonctionnalité de ramda
  • faire votre propre exemple
  • l'expliquer aux autres

Tasks-running et webpack

  • Un échafaudage en Node.js pour tous les projets JS (front ou back)
  • Web pack lance automatiquement des commandes pour nous
    • build minifié, babel, scss, typescript, npm modules...
    • live-server avec HMR pour faire tout ça en live sur un port choisi
  • S'installe avec
    • npm init && npm install webpack webpack-cli --save-dev
    • un fichier webpack.config.js décrivant au moins un fichier de base contenant le code
    • différents "loaders" pour faire nos tâches de build
      • npm i --save-dev babel-loader @babel/core @babel/preset-env
      • ajouter un "rule" pour js
      • npm i --save-dev file-loader: ajouter une rule pour les assets
      • npm i --save-dev html-webpack-plugin: plugin pour le HTML
      • npm i --save-dev webpack-dev-server: conf pour live HMR

Impasses

  • Symbol
  • Iterators
  • Generators

Ce qu'il faut potasser un peu

  • Méthodes d'Array (find, pop, ...) 
  • Bullet Two
  • Bullet Three

THANK'S EVERYONE
It's finally done ! See you soon

JavaScript 2021 - De ES6 à ESNext

By Loïc TRUCHOT

JavaScript 2021 - De ES6 à ESNext

Formation au JavaScript moderne, en français et sans compromis.

  • 738