6 fonctionnalités JavaScript à connaître

Publié: 2020-09-24

Il y a un peu plus d'un an, nous parlions des 5 "nouvelles" fonctionnalités JavaScript que vous devez connaître pour développer confortablement dans Gutenberg. Nous y avons appris ce que sont la déstructuration d'objets et de tableaux, comment créer des fonctions fléchées, ce que sont les opérateurs de propagation et de repos, etc. Heureusement, JavaScript possède encore de nombreuses fonctionnalités qui, une fois familiarisées avec elles, vous aideront à écrire un code plus intelligible et succinct.

Aujourd'hui, je vais vous montrer six fonctionnalités JavaScript vraiment cool. Opérateurs, portée variable, promesses, fonctions asynchrones… êtes-vous prêt à tout apprendre ?

#1 Chaînage optionnel en JavaScript avec l'opérateur ?.

L'opérateur de chaînage facultatif permet un accès simplifié aux attributs d'un objet lorsqu'il y a une chance que l'un soit undefined ou null . Par exemple, supposons que vous ayez un objet comme celui-ci :

 const toni = { name: 'Antonio', details: { age: 35, }, };

Pour accéder à l' age de toni , vous devez d'abord accéder à l'attribut details puis age :

 function getAge( person ) { return person.details.age; }

Le problème que nous avons dans la fonction précédente, et je suis sûr que ce n'est pas nouveau pour vous, c'est que les propriétés que nous attendons de la person ne sont pas toujours là. C'est-à-dire que si person ou person.details est undefined , la fonction ci-dessus déclenchera une erreur de type :

 getAge( toni ); // 35 getAge( {} ); // Uncaught TypeError: person.details is undefined

Habituellement, nous surmontons ce problème en ajoutant quelques gardes de sécurité :

 function getAge( person ) { if ( ! person ) { return; } if ( ! person.details ) { return; } return person.details.age; } getAge( toni ); // 35 getAge( {} ); // undefined

qui le résolvent clairement. Malheureusement, la fonction résultante est plus complexe et contient beaucoup de code bruyant qui détourne notre attention des choses qui comptent vraiment. Pour se remettre sur les rails et fixer la solution de manière plus simple, il suffit d'utiliser l'opérateur de chaînage optionnel ?. :

 function getAge( person ) { return person?.details?.age; } getAge( toni ); // 35 getAge( {} ); // undefined

Essentiellement, cet opérateur nous permet d'accéder à chaque propriété tant qu'elle n'est pas undefined ou null . Dès qu'il détecte que nous essayons d'accéder à une propriété d'un objet inexistant, il renvoie undefined .

# 2 Opérateur de coalescence nulle ( ?? )

En JavaScript, il est très facile de définir une valeur par défaut pour une variable en utilisant cet opérateur : || , droit? Tort! Nous avons tous fait cela, mais cela peut entraîner des effets secondaires inattendus si vous ne faites pas attention…

Par exemple, supposons que nous ayons un sélecteur dans notre magasin Redux qui nous permet de récupérer une valeur définie par l'utilisateur. Si l'utilisateur n'a pas encore spécifié de valeur (c'est-à-dire que la valeur est undefined ), nous renvoyons une valeur par défaut en utilisant || :

 function getValue( state ) { return state.value || 5; }

Voyons maintenant quelques exemples de ce que nous obtiendrions avec la fonction précédente après que l'utilisateur ait défini une valeur ou une autre :

 // No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 5

Oups ! Tout a bien fonctionné jusqu'à ce que nous atteignions le dernier cas ! Apparemment, si l'utilisateur définit la valeur sur 0 , le résultat de la fonction devient 5 . Pourquoi? Eh bien, la logique est assez évidente : x||y renvoie y si, et seulement si, x est une valeur « fausse ». Cela fonctionne généralement bien, car undefined est une valeur fausse. Mais il en va de même pour false ou 0 , par exemple.

En réalité, nous voulions uniquement définir une valeur default lorsqu'il n'y en avait pas. Nous pouvons donc ajouter une protection pour vérifier s'il y a une valeur ou non :

 function getValue( state ) { if ( undefined === state.value ) return 5; return state.value; }

et nous pouvons même l'écrire en utilisant l'opérateur ternaire si nous nous sentons fantaisistes :

 function getValue( state ) { return undefined === state.value ? 5 : state.value; }

mais, encore une fois, les deux solutions compliquent inutilement le code. Pour attribuer une valeur par défaut à une variable, nous devons utiliser l'opérateur de coalescence nul ?? , qui renvoie la partie droite si, et seulement si, la partie gauche est null ou undefined :

 function getValue( state ) { return state.value ?? 5; }

et, surprise-surprise !, le résultat est exactement ce que nous voulions :

 // No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 0

Oh, et, au fait, vous pouvez utiliser cet opérateur combiné avec une affectation. Par exemple, ceci :

 value = value ?? 5;

est équivalent à ceci :

 value ??= 5;

#3 Promesses et fonctions asynchrones

Les promesses sont un mécanisme implémenté en JavaScript qui nous permet de simplifier notre code source lorsque nous travaillons avec des opérations asynchrones, c'est-à-dire des opérations dont les résultats ne sont pas immédiatement disponibles. Par exemple, si nous voulons récupérer des données de notre serveur, il est clair que la réponse ne sera pas instantanée, car nous devons attendre que le serveur reçoive la requête, la traite et nous renvoie la réponse.

Dans les anciennes versions et bibliothèques JavaScript (par exemple, jQuery), nous avions l'habitude d'implémenter cela avec des rappels. L'idée était assez simple : avec la requête elle-même, définir la fonction (le callback) qui doit être appelée une fois la réponse disponible. De cette façon, lorsque l'opération asynchrone (c'est-à-dire la récupération des données du serveur) se termine, la bibliothèque appellera la fonction et notre logique reprendra :

 jQuery.ajax( { url: 'https://server.com/wp-json/wp/users/1', success: ( user ) => { console.log( user ); }, } );

Si nous ne déclenchons qu'une seule requête isolée, cette solution est assez élégante et pratique. Mais, dès que nous devons effectuer plus de requêtes, les choses se salissent rapidement. Par exemple, si nous voulons demander à deux utilisateurs différents, nous devrons imbriquer les rappels :

 jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/1', success: ( user1 ) => { jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/2', success: ( user2 ) => { console.log( user1, user2 ); }, } ); }, } );

Les promesses sont la solution à ce problème : si l'obtention d'un certain résultat n'est pas immédiate (comme, par exemple, lorsque l'on récupère quelque chose d'un serveur), on peut tout de suite retourner une promesse JavaScript. Cet objet est un wrapper de la valeur réelle et signifie la "promesse" que ladite valeur sera disponible à un moment donné dans le futur.

Par exemple, si nous devions réécrire notre premier extrait en utilisant des promesses, cela ressemblerait à ceci :

 const promise = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); promise.then( ( user ) => console.log( user ) );

Comme vous pouvez le voir, wp.apiFetch doit récupérer l'utilisateur 1 du serveur, mais il donne immédiatement un résultat. Le résultat, cependant, n'est pas l'utilisateur lui-même, mais une promesse qui sera résolue par l'utilisateur une fois les demandes terminées. Par conséquent, tout ce que nous avons à faire est d'écrire un rappel qui traitera la réponse de la promesse lorsqu'elle sera résolue.

Vous pensez peut-être maintenant que ce n'est pas si difficile par rapport à ce que nous avions auparavant, n'est-ce pas ? Après tout, nous utilisons toujours des rappels… mais vous pouvez voir à quel point cela est utile une fois que nous commençons à combiner plusieurs requêtes :

 const promise1 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); const promise2 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/2', } ); Promise.all( [ promise1, promise2 ] ).then( ( [ user1, user2 ] ) => console.log( user1, user2 ); );

En utilisant des promesses, nous avons pu lancer deux requêtes parallèles pour récupérer les utilisateurs 1 et 2 et utiliser Promise.all pour attendre la résolution des deux promesses. Pas de code spaghetti avec des rappels imbriqués impliqués.

Eh bien, la grande chose à propos des promesses est encore sur le point de venir. Nous pouvons utiliser du sucre syntaxique pour travailler avec les promesses JavaScript et écrire du code asynchrone qui a l'air, eh bien, synchrone. Tout ce que vous avez à faire est de définir une fonction asynchrone en utilisant le mot-clé async et tout à coup les choses deviennent beaucoup plus faciles :

 async function logTwoUsers( id1, id2 ) { const user1 = await wp.apiFetch( { url: '…' + id1 } ); const user2 = await wp.apiFetch( { url: '…' + id2 } ); console.log( user1, user2 ); }

Chaque fois que vous appelez une opération asynchrone dans une fonction asynchrone, vous pouvez attendre son résultat à l'aide du mot clé await . La seule chose que vous devez garder à l'esprit est que, lorsque vous définissez une fonction async , son résultat sera toujours une promesse :

 async function getNumberFive() { return 5; } const p = getNumberFive(); // a promise p.then( console.log ); // prints "5"

#4 Portée variable lors de l'utilisation de let et const

Comme vous le savez probablement déjà, vous pouvez maintenant déclarer des variables en utilisant les mots-clés let et const . Le premier définit une variable et le second définit une constante :

 let x = 1; console.log( x ); // 1 x = 2; console.log( x ); // 2 const y = 1; console.log( y ); // 1 y = 2; // Uncaught TypeError: invalid assignment to const 'y' console.log( y ); // 1

Vous pourriez être tenté de penser que let et var sont la même chose, car les deux mots clés nous permettent de déclarer une variable non constante. Mais il existe une différence substantielle entre eux : leur portée. Avec let et const , la portée de la variable est le bloc où elle est définie. Dans var , c'est toute la fonction.

 function fn() { if ( true ) { var x = 1; let y = 2; const z = 3; }//end if console.log( x ); // 1 console.log( y ); // Uncaught ReferenceError: y is not defined console.log( z ); // Uncaught ReferenceError: z is not defined }

# 5 Transformation des données lors de l'utilisation JSON.parse

La fonction JSON.parse analyse une chaîne JSON et crée un objet JavaScript. Par exemple:

 const x = JSON.parse( '{"x":1,"a":[1,2,3]}' ); // Object { x: 1, a: [ 1, 2, 3 ] }

Ce que la plupart des gens ne savent pas, c'est qu'il prend en charge un deuxième argument appelé reviver . Ce paramètre est une fonction qui sera exécutée pour chaque élément en cours d'analyse, vous permettant de manipuler la valeur à votre guise. Par exemple, imaginez une chaîne JSON comme celle-ci :

 const json = '{"name":"David","birthday":"1985-12-01T10:00:00.000Z"}';

Si nous utilisons JSON.parse tel quel, il générera un objet avec deux attributs de chaîne : name et birthday . Mais si nous fournissons une fonction de JSON.parse reviver nous pouvons nous assurer que l' birthday est analysé en tant que Date :

 const user = JSON.parse( json, ( key, value ) => 'birthday' === key ? new Date( value ) : value )

# 6 Séparateur numérique dans le code source utilisant le caractère de soulignement ( _ )

Notre dernier conseil aujourd'hui est le séparateur numérique. Il existe une proposition (actuellement à l'étape 4) qui permet d'écrire des nombres d'une manière qui facilite la compréhension pour les humains. Par exemple, pouvez-vous vraiment dire quelle est la taille des nombres suivants ?

 10000000000 2189719.25

Si seulement nous pouvions utiliser le séparateur de milliers, ce serait beaucoup plus facile à interpréter ! Et c'est précisément ce que nous pouvons faire en utilisant le trait de soulignement _ :

 10_000_000_000 2_189_719.25

Sommaire

Il est possible d'écrire un meilleur code JavaScript si vous vous habituez à tous les nouveaux outils et fonctionnalités inclus dans JavaScript. Aujourd'hui, nous avons vu plusieurs exemples de ce qui est possible avec ce langage de programmation. J'espère que vous avez appris quelque chose de nouveau et si vous l'avez aimé, n'oubliez pas de le partager avec vos collègues. À bientôt!

Image sélectionnée par Sam Dan Truong sur Unsplash.