2020

Switch case en action

voici le test pour rechercher dans un string les caractère < ou >
  1.     switch (string.charCodeAt(index)) {
  2.        case 60: // <
  3.         escape = '&lt;';
  4.         break;
  5.       case 62: // >
  6.         escape = '&gt;';
  7.         break;
  8.       default:
  9.         continue;
  10.     }
code

module

ES6

  1. // List of the characters to escape 
  2. const chars = {
  3.     ">": "&gt;",
  4.     "<": "&lt;",
  5. };

  6. //  RegExp from the `chars` object
  7. const re = new RegExp(Object.keys(chars).join("|"), "g");

  8. // Return the escaped string
  9. const escapeHtml = (str = "") => String(str).replace(re, match => chars[match]);

  10. console.dir( escapeHtml('<div>'));


Filtre


  1. const filter = 

  2.   (fx, array) => array.reduce(

  3.     (acc, item) => fx(item) ? acc.concat(item) : acc, 

  4.   []);

  5. const greaterThan4 = (x) => x >= 4;

  6. const data   = [0, 1, 2, 3, 4, 5];

  7. let result = filter(greaterThan4, data);


code

VS et module pour node

J'aimerais utiliser The lodash method _.partition exported as a Node.js module.


Ainsi, ouvrez un terminal et comme l'indique la documentation tapez
npm i --save lodash.partition puis tapez Entrée (return).

on peut ensuite ajouter, en début de fichier, le module

let partition = require('lodash.partition');


code

let partition = require('lodash.partition');

let users = [
  { 'user': 'barney''age': 36'active': false },
  { 'user': 'fred''age': 40'active': true },
  { 'user': 'pebbles''age': 1'active': false }
];

let u = partition(usersfunction (o) { return o.active; });
console.dir(u);

$ node app.js (le nom de votre fichier) [ [ { user: 'fred', age: 40, active: true } ], [ { user: 'barney', age: 36, active: false }, { user: 'pebbles', age: 1, active: false } ] ]

Intégration dans un fichier


  <script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>


let arr = [8, null, 32, 'foo', NaN, 'bar', false, {}, 64, 128];
let parts = _.partition(arr, (el) => {
        return typeof el === 'number' && !_.isNaN(el);
    });
console.log(parts[0]); // [8, 32, 64, 128]


Reduce for ever

Nous allons tenter de comparer l’efficacité de différents code pour l'obtention des valeurs Min, Max et la somme des nombre d'un tableau.

Nous commençons par définir un immense tableau data de 50000 objets.
  1. const data = [];
  2. const random = (min, max) => Math.floor(Math.random() * (max - min)) + min;
  3. for (let i = 0; i < 50000; i++) {
  4.     data.push({ x: random(11000000) });
  5. }

Reduce

Nous pouvons réduire le tableau à un objet contenant les valeurs :
  1. console.time("reduce");   
  2. let {min, max, sum} = data.reduce(function( {max, min, sum}, {x}) {

  3.     min = Math.min(min,x);
  4.     max = Math.max(max,x);
  5.     sum = sum + x;
  6.     return { min, max, sum}
  7.  },
  8.  {min : Number.MAX_VALUE,
  9.  max : Number.MIN_VALUE,
  10.  sum : 0
  11.  });
  12. console.timeEnd("reduce");

  13. console.log( min, max, sum );

Autre

Nous utilisons ici la méthode map qui transforme le tableau d'objets en tableaux de valeurs


  1. console.time("map");    
  2. const mapData = data.map(i => i.x);
  3. const maxData = Math.max(...mapData);
  4. const minData = Math.min(...mapData);
  5. for (let i = 0, sum = 0; i < data.length; sum += data[i++]);
  6. console.timeEnd("map");
  7. console.log(minData,maxData,sum);

Résultats de la comparaison

$ node comparaisonMin.js reduce: 12.563ms 15 999996 24956286473 map: 24.679ms 15 999996 24956286473 $ node comparaisonMin.js reduce: 16.015ms 5 999997 25029524292 map: 26.572ms 5 999997 25029524292

Range

Opérations élémentaires :


console.log(/^0b[01]+$/i.test("0b0011"));

console.log(/^0b[01]+$/i.test("0b0013"));
console.log("0b0011".slice(2));
console.log(parseInt("0011", false ? 2 : 8))

console.log("0o0011".slice(2));
console.log(parseInt("0011", true ? 2 : 8))
console.log()


let reTrim = /^\s+|\s+$/g,

    reIsBinary = /^0b[01]+$/i,
    reIsOctal = /^0o[0-7]+$/i,
    reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

function toNumber(value) {
    if (typeof value == 'number') {
        return value;
    }

    if (typeof value != 'string') {

        return value === 0 ? value : +value;
    }
    value = value.replace(reTrim, '');
    let isBinary = reIsBinary.test(value);
    return (isBinary || reIsOctal.test(value))
        ? parseInt(value.slice(2), isBinary ? 2 : 8)
        : (reIsBadHex.test(value) ? NAN : +value);
}


console.log( toNumber("     0b0011 "))

code


Range

range(0b011"10"1)

[ 3, 4, 5, 6, 7, 8, 9 ]


range("  0b011 ""     000005""NON")
[ 3, 3 ]

range("  0b011 ""     000005"" 0o1")
[ 3, 4 ]

code

Transposée d'une matrice

Closure :

Examiner le code Python

def myfunc(n):
  return lambda a : a * n

mydoubler = myfunc(2)

print(mydoubler(11))

En JS,

function mult(nb){
   return v=>v*nb
}

let triple = mult(3);

triple(3);

La mémorisation est obtenue par une fermeture (closure)
La figure ci dessous est obtenue dans un débogueur, elle montre explicitement la fermeture.


Itérateurs : SYMBOL


const m = 'myMethod';
class Foo {
    [m]() {}
}

Donc, on pourra écrire : 

class IterableClass {
    [Symbol.iterator]() {
        ···
    }
}

Deep destructuration

Exemple

const itemInfos = [
{name:"id20199",infos:{min:66864,max:66927}},
{name:"id34555",infos:{min:7615,max:119296}}
]




let min1 = itemInfos[0].infos.min;


for (let { infos: { min } } of itemInfos) {

    console.log(` la valeur min = ${min}`);

}

code

Cas des tableaux



Trie avec le premier élément du tableau comme critère.

COMPAGNIES.sort( ({ ranges: [A] } , {ranges: [B] }) => A < B );

code

Passage des arguments


  1. function baseRange(start, end, step=1, fromRight=false) {
  2.     let index = -1,
  3.         length = Math.max(Math.ceil((end - start) / (step)), 0),
  4.         result = Array(length);

  5.     while (length--) {
  6.       result[fromRight ? length : ++index] = start;
  7.       start += step;
  8.     }
  9.     return result;
  10.   } 
  11. let t = baseRange(0,9,4,false);
  1. const baseRange = function (...arg) {
  2.     let [start, end, step = 1, fromRight = false] = arg;
  3.     let index = -1,
  4.         length = Math.max(Math.ceil((end - start) / (step)), 0),
  5.         result = Array(length);
  6.     while (length--) {
  7.         result[fromRight ? length : ++index] = start;
  8.         start += step;
  9.     }
  10.     return result;
  11. }
  12. let t = baseRange(094false);

code

Test A fond la forme

range("  0b011 "," 5",0.5));

Range avec test ! 


Notion avancée


Notez également l'utilisation d'un générateur


 let range = function(start,end,step){
   
   return {
    *[Symbol.iterator]() {
          let value = start;
          while (value < end) {
              yield value;
              value = value + step;
          }
   }
   }
 }

 for (let e of range(1,6,2)) console.log(e);
 let [a,b,...c] = [...range(1,6,1)]
 console.log(a,b,c)




Reduce à fond la forme 6

reduce 1
reduce 2
reduce 3
reduce 4
reduce 5

Améliorations


const words = [10,2,2,1,10,10,10,10,10];

const o = words.reduce((a, x) => {
   if (!a[x]) a[x] = 0;
   a[x]=a[x]+1;
return a},{});

Reduce à fond la forme 5

reduce 1
reduce 2
reduce 3
reduce 4

Amélioration


const words = [0,2,0,0,6];


let t = words.reduce(function( {max, min}, x) {
   min = Math.min(min,x);
   max = Math.max(max,x);
   return { min, max }
},
{min : Number.MAX_VALUE,
max : Number.MIN_VALUE,
});



const nbOccurences = words.reduce((a, x) => {
   a[x]= a[x]+1;
return a},Array.from({length:t.max+1},()=>0));



Reduce : à fond la forme 4

reduce 1
reduce 2
reduce 3

Améliorations :


const words = [1,2,2,1,5];

let { max, average } = words.reduce(function( {max, min, sum, nb}, x) {

   min = Math.min(min,x);
   max = Math.max(max,x);
   sum = sum + x;
   let average = sum/++nb;

   return { min, max, nb, sum, average, nb }

},
{min : Number.MAX_VALUE,
max : Number.MIN_VALUE,
sum : 0,
average : 0,
nb : 0});

🥷la valeur initiale est un 🥇objet et quel objet !

console.log(average, max);

Reduce : à fond la forme 3

reduce 1
reduce 2

Amélioration

const words = [1,2,2,1,5];


let { min, max } = words.reduce(function( {max, min}, x) {

   min = Math.min(min,x);
   max = Math.max(max,x);

   return { min, max }

},
{min : Number.MAX_VALUE,
max : Number.MIN_VALUE});

🥷la valeur initiale est un objet ! 

console.log(min,max);

Reduce : fond la forme 2


reduce 1

Amélioration :


const words = [1,2,2,1,5];


let { min } = words.reduce(function( {min}, x) {

   min = Math.min(min,x);

   return { min }

},
{min : Number.MAX_VALUE});


🥷la valeur initiale de l'acuumulateur est une objet !


console.log(JSON.stringify(min));

Reduce : à fond la forme

const words = [1,2,2,1,5];

let min = words.reduce(function(acc, x) {

   acc = Math.min(acc,x);

   return acc

},Number.MAX_VALUE);

🥷la valeur initiale est une valeur !


console.log(min);

olet min = words.reduce( (acc, x) => Math.min(acc,x),Number.MAX_VALUE);


code

fonction : objet

Une fonction est un objet qui possède donc des propriétés.

On peut "cacher" des résultats, voici un exemple avec la plus lente fonction de fibonachi

f(n) {
   if (n<= 1) return n;
   return f(n - 1) + f(n - 2);
}

/**
 *                         f(5)
 *                   /              \
 *                f(4)                f(3)
 *             /       \             /    \
 *          f(3)       f(2)        f(2)   f(1)
 *         /    \      /   \       /   \   
 *      f(2)   f(1)  f(1)  f(0)  f(1)  f(0)  
 *      /   \   
 *    f(1) f(0)  

let fib = function (n) {
  if ( fib.cache[n] ) { 
    return fib.cache[n]; 
  } 
  else { 
     if (n<= 1) {
       fib.cache[n] = n
       return n;
       }
     let u = fib(n - 1) + fib(n - 2);
       fib.cache[n] = u; 
       return u;
  }

  return results;
};

fib.cache={};


console.time("appel 1");
console.log(fib(9));
console.timeEnd("appel 1");
console.time("appel 2");
console.log(fib(10));
console.timeEnd("appel 2");
code

P.S. pas de récursif pour fibo dans tous les cas.
Ecrire un programme pour intégrer des vidéos


Exemples : web component

https://mdn.github.io/web-components-examples/

import : espace de nom !

import {ItemList} from './item.js';
//import {qs, $on} from './helpers.js';
import * as Help from './helpers.js';
import Template from './template.js';


export default class View {
/**
* @param {!Template} template A Template instance
*/
constructor(template) {
this.template = template;

this.$todoList = Help.qs('.todo-list');
this.$newTodo = Help.qs('.new-todo');
}

Promise : Training

Une promesse est un objet auquel on attache des callbacks plutôt que de passer des callbacks à une fonction.

Une promesse est comme un bipeur de restaurant.

Vous partez avec le bipeur (une promesse).
Vous êtes libre de faire autre chose.


Codelab


https://codelabs.developers.google.com/codelabs/pwa-promises/index.html?index=..%2F..dev-pwa-training#0

Google I/O ’19


Avec par ordre :

private class fields 6:57 Regex matchAll 9:16 Numeric literals 10:19 BigInt formatting 11:50 flat & flatmap 13:23 fromEntries 15:28 Map to Object conversion 16:47 globalThis 19:18 Stable sort 20:00 Intl.RelativeTimeFormat 22:45 Intl.ListFormat 24:29 Intl.DateTimeFormat -> formatRange 26:32 Intl.Locale 27:10 Top-Level await 28:12 Promise.allSettled/Promise.any 31:13 WeakRef 32:30

Class et extend : en action

fonction délégation

Utils.js

function $delegate(target, selector, type, handler, capture) {
const dispatchEvent = event => {
const targetElement = event.target;
const potentialElements = target.querySelectorAll(selector);
let i = potentialElements.length;

while (i--) {
if (potentialElements[i] === targetElement) {
handler.call(targetElement, event);
break;
}
}
};

  target.addEventListener(type, dispatchEvent, !!capture);
}

Utilisation

$delegate(target,"span","mouseover",show,true)

module : en action

Création du fichier helper.js

/**
 * querySelector wrapper
 *
 * @param {string} selector Selector to query
 * @param {Element} [scope] Optional scope element for the selector
 */
export function qs(selector, scope = document) {
return scope.querySelector(selector);
}

/**
 * addEventListener wrapper
 *
 * @param {Element|Window} target Target Element
 * @param {string} type Event name to bind to
 * @param {Function} callback Event callback
 * @param {boolean} [capture] Capture the event
 */
export function $on(target, type, callback, capture) {
target.addEventListener(type, callback, !!capture);
}

/**
 * Attach a handler to an event for all elements matching a selector.
 *
 * @param {Element} target Element which the event must bubble to
 * @param {string} selector Selector to match
 * @param {string} type Event name
 * @param {Function} handler Function called when the event bubbles to target
 *                           from an element matching selector
 * @param {boolean} [capture] Capture the event
 */
export function $delegate(target, selector, type, handler, capture) {
const dispatchEvent = event => {
const targetElement = event.target;
const potentialElements = target.querySelectorAll(selector);
let i = potentialElements.length;

while (i--) {
if (potentialElements[i] === targetElement) {
handler.call(targetElement, event);
break;
}
}
};

$on(target, type, dispatchEvent, !!capture);
}

/**
 * Encode less-than and ampersand characters with entity codes to make user-
 * provided text safe to parse as HTML.
 *
 * @param {string} s String to escape
 *
 * @returns {string} String with unsafe characters escaped with entity codes
 */
export const escapeForHTML = s => s.replace(/[&<]/g, c => c === '&' ? '&amp;' : '&lt;');

Utilisation de la fonction $on dans un fichier 

Voici la structure de l'application
avec dans le répertoire src : 

Pour utiliser la fonction $on dans app.js on écrit : 

import {$on} from './helpers.js';

Dans le fichier index.html, on utilise le code

<script src="src/app.js" type="module"></script>

Serveur

on peut utiliser simplement l'extension sous chrome.

Exemple en ligne





template

Utilisation de template :

/**
 *
 * @constructor
 */
class Template {

  constructor() {
    this.defaultTemplate = ` // notez le `
    <li data-id="{{id}}" class=""> // notez {{}} un code utilisé pour remplacer la valeur
      <div class="view">
        <input class="toggle" type="checkbox" />
        <label>{{title}}</label>
        <button class="destroy"></button>
      </div>
    </li> 
  ` // fin 
  }

  show = function(data) { //data = [tableau d'objets issus d'une bibliothèque]

    let view = ''

    for (let v of data) { // v est un objet contenant les informations
      let template = this.defaultTemplate;

      template = template.replace('{{id}}', v.id)
      template = template.replace('{{title}}', v.title)


      view = view + template
    }

    return view // une concaténation de <li>
  }
}

let view = new Template();
let li = view.show([{
    id: 1,
    title: "Hello",
  },
  {
    id: 2,
    title: "World",
  }
])

// insertion des <li> dans le DOM <ul>
document.querySelector(".todo-list").insertAdjacentHTML("afterbegin", li);




Remarque :

on pourra préférer cette écriture utilisant la méthode reduce sur le tableau items 

items.reduce((acc, item) => acc + `
<li data-id="${item.id}"${item.completed ? ' class="completed"' : ''}>
<div class="view">
<input class="toggle" type="checkbox" ${item.completed ? 'checked' : ''}>
<label>${item.title}</label>
<button class="destroy"></button>
</div>
</li>`, '');