CM Bonus
CM Bonus
CM Bonus
Objectif
Aborder des fonctions « avancées » de JS, et intégrer des dépendances tierces dans nos scripts.
A noter que ces fonctions plus avancées ne sont pas essentielles, dans le sens que vous pouvez très bien
réussir à refaire les mêmes choses avec vos connaissances actuelles. Cependant, il reste important de les
connaître et d’en faire usage quand pertinent et au détriment des fonctions basiques car c’est non seulement
plus lisible, mais c’est surtout plus performant, et c’est largement utilisé dans des projets JavaScript dans
tous les domaines.
Ce modèle universel fonctionne bien, mais peut vite devenir lourd lorsque l’on souhaite incorporer des quotes
dans nos strings, ou rajouter des variables à l’intérieur par exemple :
Il y a une façon plus simple d’écrire un string paramétré comme ça, en utilisant la notation avec des
« backticks » : `. Ce caractère est également utilisé dans le cadre de requêtes SQL par exemple. Vous
pouvez saisir ce caractère sur un clavier AZERTY français standard avec AltGr + 7 suivi d’un appui sur la
touche ESPACE. Cette notation s’appelle un « template litteral », et permet d’utiliser librement des simples
et doubles quotes dans un string. De plus, il est possible de faire des retours à la ligne sans utiliser des
« \n ». Mais encore plus utile, il est possible d’incorporer des expressions directement dans une chaîne, sans
passer par de la concaténation en utilisant « ${myExpression} ».
C’est dans l’ensemble une notation beaucoup plus propre et flexible pour faire des chaînes complexes et
paramétrées. L’exemple ci-dessus avec un « template litteral » s’écrirait ainsi :
Dans l’exemple ci-dessus, les expressions dans les ${…} sont des simples variables, mais il est possible de
mettre n’importe quelle expression JS valide qui retourne un résultat :
function carre(num) {
return `Le chiffre ${num} au carré vaut ${num * num}`;
}
Dans l’ensemble, ce n’est pas une notation compliquée, et ça peut rendre la logique de manipulation de
certains strings beaucoup plus lisible. Tout bénef !
Typiquement, pour parcourir un tableau, vous avez l’habitude d’effectuer des boucles. En pratique, c’est une
bonne façon de faire, et ça fonctionne plutôt bien. Cependant, les boucles for traditionnelles font un très
mauvais travail pour « signaler » en un coup d’œil à quoi elle sert et comment elle opère.
Le JavaScript met à disposition quelques fonctions liées aux tableaux qui permettent de facilement travailler
avec sans passer par des boucles traditionnelles.
A) La fonction « map »
1) Le concept
Dans son état le plus simple, la fonction « map » d’un tableau permet de transformer l’intégralité d’un tableau
en autre chose. Elle se compose ainsi :
Ainsi, la fonction map prend un unique paramètre callback qui doit donc être une fonction. Ce callback sera
appelé pour chaque entrée dans le tableau d’origine, et la valeur retournée dans ce callback sera la nouvelle
entrée dans le nouveau tableau qui sera retourné.
Par exemple :
Pour chaque entrée dans le tableau oldArray, on a donc exécuté la fonction en callback, et la valeur retournée
est la valeur qui prendra place dans le nouveau tableau qui sera construit.
La fonction map fonctionne aussi très bien avec des tableaux d’objets, et permet par exemple de parcourir
un tableau d’entrées générique pour les transformer en éléments HTML à incorporer dans le DOM.
Par exemple :
const items = [
{ id: 1, name: "Test" },
{ id: 2, name: "Test2" },
];
items.map((item) => {
item.name = "TestMutate";
return item;
});
Ce map retournera bien un tableau avec deux objets dont le nom vaut “TestMutate”, mais vu qu’on a affecté
la valeur “item”, le tableau d’origine sera aussi changé!
Enfin, la fonction map va quoi qu’il arrive parcourir tout le tableau, et créer un nouveau tableau de la même
taille, même si dans la fonction callback rien n’est retourné. Si vous omettez de retourner quelque chose, la
valeur à cet index du tableau vaudra "undefined".
Une fois un map lancé, il n’est pas possible d’en sortir, contrairement à une boucle for classique où l’on
pourrait utiliser un « break ».
B) La fonction « filter »
Un cousin très utile à la fonction map est la fonction filter. Elle fonctionne de façon similaire dans le sens
qu’elle prend un callback, et retourne un nouveau tableau. La fonction principale de filter est de produire un
nouveau tableau avec seulement des éléments qui remplissent une condition qu’on définit dans la fonction
callback.
Si la fonction de callback retourne une valeur « truthy », la valeur sera incluse dans le tableau final. Au
contraire, si elle récupère une valeur « falsy », elle sera omise dans le tableau final.
Exemple :
const words = [
"spray",
"limit",
"elite",
"exuberant",
"destruction",
"present",
];
const result = words.filter((word) => word.length > 6);
console.log(result); // => ["exuberant", "destruction", "present"]
On voit donc que le résultat produit est un nouveau tableau dont les entrées auraient retourné une valeur
« truthy » dans la fonction de callback.
C) La fonction « forEach »
Vous avez peut-être déjà utilisé cette fonction, ou remarqué l’usage de cette fonction dans les corrections
des précédents TDs. Comme son nom l’indique, un forEach, va parcourir tous les éléments d’un tableau, et
simplement exécuter la fonction passée en callback de façon successive. Il n’y a pas de fonctions particulière
associée contrairement au map et au filter dans la mesure que la valeur de retour de la fonction est
ignorée/inutile. De plus, un forEach ne retourne pas un nouveau tableau. C’est ainsi une fonction plus
générique, mais qui reste utile dans certaines circonstances.
Il y a plein de situations où un simple forEach peut être suffisant pour votre use case. Mais évitez simplement
d’utiliser la fonction forEach pour recréer une sorte d’équivalent à un .map ou un .filter, c’est contre-productif !
D) La fonction « reduce »
La dernière fonction que nous allons tacler est un peu plus particulière. Son but premier est de « réduire »
un tableau à une nouvelle valeur. Prenons l’exemple concret suivant ; Nous avons un tableau de numbers,
et nous voulons avoir la somme de chacun des éléments du tableau. On pourrait l’écrire ainsi :
Si on décompose ce qu’on vient de voir, on remarque que la fonction se reduce un peu des autres fonctions
map, filter, forEach qu’on a vu précédemment. Elle prend en premier argument ce qu’on appelle typiquement
l’accumulateur, et en deuxième, la valeur courrante. La fonction callback retourne une valeur, et celle-ci sera
la nouvelle valeur de l’accumulateur dans la prochaine itération. Le deuxième argument de reduce est la
valeur initiale que vaut l’accumulateur lors de la première itération. A la fin, la fonction reduce retourne la
valeur finale de l’accumulateur.
E) Note de fin
Il existe une pléthore de fonctions dites « avancées » sur les tableaux. Cette section du cours liste, selon
moi, les plus importantes, et celles qui sont les plus répandues. Cependant, n’hésitez pas à faire un tour
rapide sur le MDN sur la section Arrays pour voir d’autres possibilités pour votre curiosité personnelle:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array. Cette ressource
est également très bien pour trouver des compléments d’informations sur les fonctions que nous venons de
décrire.
Ces fonctions tableau sont très pratiques, et très facile à écrire une fois que vous prenez la main avec. C’est
également très pratique pour manipuler des tableaux d’objets.
A) La notation « spread »
La notation spread se caractérise par l’utilisation de « … » juste avant un objet ou un array. Elle permet de
façon simplifiée d’itérer sur un objet, de la même façon qu’on le ferait avec une boucle for, et retourne les
éléments individuels qui le composent.
Par exemple :
Cette notation permet d’itérer sur les clés de l’objet user, et de les recréer dans un nouvel objet. Mais l’utilité
ne s’arrête pas là, par exemple :
On créé ici un nouvel objet, qui prend les propriétés de base dans l’objet « user », mais on lui définit une
nouvelle propriété « isAdmin », et on lui définit en plus une nouvelle propriété pour la clé « name » qui viendra
remplacer celle de l’objet initial.
En connaissant les règles par rapport aux références d’objets et comment elles sont stockées dans des
variables, la notation spread est une façon très rapide et compréhensive de créer ou modifier des objets
basés sur un objet existant.
La notation spread peut également être utilisée pour créer des fonctions avec un nombre indéfini
d’arguments :
Le paramètre « …args » est un tableau contenant tous les paramètres passés à la fonction. C’est un tableau
comme un autre, et peut donc contenir 0 entrées, ou une infinité. C’est pratique pour certaines
implémentations de quelques fonctions spécifiques.
B) La déstructuration d’objets
1) La base
Dans beaucoup de cas en JavaScript, on manipule des objets entiers, mais on n’a pas besoin d’avoir
l’intégralité des clés de l’objet. La déstructuration est une façon de sortir uniquement les clés dont on a besoin
d’un objet.
Avec cette écriture, on récupère “name” sous forme de const qui était dans l’objet user à la base, et on peut
l’utiliser sans avoir à faire « user.name ».
document
.querySelector("button")
.addEventListener("click", ({ target }) => console.log(target));
Dans l’exemple ci-dessus, on a à faire à une fonction de callback tout ce qui a de plus classique suite à un
évènement de click. Mais dans la fonction callback, à la place de récupérer l’event en entier. On récupère
uniquement la clé « target » présente dans l’objet event. C’est une façon de récupérer des clés de façon
contrôlée, et de les utiliser sans exposer le reste d’un objet.
Note importante : Déstructuration != Destruction. Malgré le nom qu’on a donné à cette feature, l’objet de base
n’est aucunement affecté par cette méthode. Par contre, les règles des références des objets dans les
variables restent d’application.
2) La déstructuration et le renommage
Il est possible dans le cadre d’une déstructuration de renommer une clé pour lui donner un autre nom :
Le fait de rajouter un « : » suivi d’un string permet de donner un nouveau nom à l’objet que l’on récupère de
la déstructuration. C’est le genre d’astuce qui est pratique si on a déjà une variable qui porte le même nom,
ou bien pour donner un nom plus explicite à la variable en question.
3) La déstructuration et le spread
On peut combiner la déstructuration avec l’opérateur spread qu’on vient de voir pour récupérer le reste des
attributs d’un objet qu’on n’a pas inclus dans notre déstructuration :
On remarque qu’on peut spread le reste des clés qu’on n’a pas inclus dans notre déstructuration. A noter
également que ce nouvel objet « rest » que l’on vient de spread ne contient pas les clés qu’on a déstructuré
juste avant, et correspond littéralement au reste de l’objet.
En téléchargeant le code JS de la librairie, et en l’incluant dans votre page web tel n’importe quel
autre fichier javascript.
Vous incluez un script distribué à partir d’un CDN (Content Delivery Network).
En utilisant des outils plus avancés tel que Node + NPM pour gérer vos dépendances
Prenons par exemple la librairie Lodash que vous pouvez consulter ici : https://lodash.com/ ; vous pouvez
l’inclure dans votre projet soit en téléchargeant la version de votre choix (préférablement la dernière) et en
l’incluant comme-ci ;
<script src="/vendor/lodash.min.js"></script>;
Ou bien en utilisant la version CDN. Il n’y a pas vraiment de règles sur comment les trouver, mais si une
librairie propose une version CDN, vous trouverez généralement le lien sur leur page de projet. Pour Lodash
par exemple, on ferait ainsi :
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Les deux méthodes sont valables et permettent de parvenir au même résultat à la fin.
A partir du moment que le script est intégré dans la page, vous pouvez du coup faire usage de la librairie tel
que spécifié sur leur page.
Comme pour vos scripts en JS en temps normal, faites attention à l’ordre de vos scripts ! Si vous tentez par
exemple d’incorporer Lodash dans votre projet après le script que vous avez conçu pour votre page, les
fonctions offertes par la librairie ne seront pas encore chargées, et du coup votre script va très certainement
ne pas fonctionner.
V/ Pour conclure…
Il ne faut pas être intimidé face à toutes ces notions. Certaines sont plus utiles que d’autres, mais si vous
connaissez bien déjà tout ce que nous avons vu dans les précédents CM de ce module, vous avez déjà une
bonne base en JS que vous allez naturellement cultiver dans la suite de vos études et votre parcours
professionnel si vous vous dirigez vers un poste où le JS est dominant. Comme je l’ai souvent répété dans
ce module, la ressource https://javascript.info/ est excellente pour creuser toutes les notions de JS qu’on n’a
pas vu ensemble ici.
La communauté JS est devenue énorme au point où énormément d’outils se sont rajoutés à l’écosystème
pour permettre de concevoir des applications toujours plus complexes.
Le JavaScript via des outils comme NodeJS permettent d’utiliser le JavaScript en dehors d’un contexte
navigateur, au point où il est possible de faire une application entière en utilisant du JavaScript en Front et
en Back. Il est même possible via des frameworks comme Electron de faire des applications « natives » pour
PC basé sur les technologies web.
Enfin, l’écosystème du JavaScript a grandi de façon exponentielle, et très rapidement au cours de la dernière
décennie. La prolifération des technologies annexes, de l’intégration plus forte sur toutes les échelles de la
stack technique, et la multiplication des frameworks, librairies, et méthodologies sont un témoin évident de
cette évolution. Bien que ceci puisse changer du jour au lendemain, il n’y a aucun signe de ralentissement
en vue.
En bref, votre exposition à tout cet écosystème sera inévitable si vous partez sur le domaine du front-end,
ou n’importe quel métier où le JavaScript est inclus dans la stack technique.