10 concepts pour améliorer votre maîtrise de JavaScript
JavaScript est incontestablement l'un des langages de programmation les plus populaires au monde et est utilisé pour créer des sites Web interactifs et des applications Web. Pour les développeurs, l'apprentissage de JavaScript peut ouvrir une multitude d'opportunités en raison de sa force et de sa polyvalence. Dans cet article, nous explorerons 10 concepts clés qui peuvent vous aider à améliorer votre maîtrise de JavaScript et à faire passer vos compétences au niveau supérieur. Ces concepts vous offriront une base solide dans le langage et vous aideront à devenir un développeur plus compétent et plus confiant.
1.Promesses
Les promesses JavaScript sont un outil puissant pour gérer les actions asynchrones dans votre code. Ils vous permettent de gérer les résultats d'une opération asynchrone, comme une requête réseau, sans bloquer l'exécution du reste de votre code. Une promesse peut être dans l'un des trois états suivants : remplie, rejetée ou en attente. Elle symbolise le résultat final d'une opération asynchrone.
Par rapport à l'utilisation de fonctions de rappel, les promesses offrent un mécanisme permettant de gérer les résultats d'une action asynchrone de manière plus rationalisée et contrôlée. De plus, ils facilitent la gestion cohérente des erreurs et enchaînent plusieurs tâches asynchrones.
Les promesses sont largement utilisées dans les bibliothèques et frameworks JavaScript, tels que AngularJS, ReactJS et Node.js. Introduits dans ES6, ils constituent un concept fondamental pour le développement JavaScript moderne. La lisibilité, la maintenabilité et les performances de votre code peuvent toutes être considérablement améliorées en sachant utiliser correctement les promesses.
Lors de l'utilisation de promesses JavaScript, l'objet " promesse " est un constructeur qui crée une nouvelle promesse et prend un seul argument, qui est une fonction appelée "exécuteur". La fonction d'exécuteur prend deux paramètres, « résolver » et « rejeter » qui peuvent être utilisés pour indiquer si l'opération asynchrone a réussi ou échoué.
Regardons l'exemple suivant :
Une fois qu'une promesse est créée, vous pouvez utiliser sa méthode " then" pour attacher les rappels qui seront invoqués lorsque la promesse est résolue, et sa méthode " catch" pour attacher les rappels qui seront invoqués lorsque la promesse est rejetée. Alternativement, vous pouvez gérer plusieurs promesses simultanément en utilisant les méthodes Promise.all() et Promise.race(). Les promesses sont disponibles dans tous les environnements JavaScript modernes et sont prises en charge dans tous les principaux navigateurs, vous pouvez donc les utiliser en toute confiance dans vos projets.
2. Asynchrone/Attente
Tout comme les promesses, la fonctionnalité « async/wait » est utilisée en JavaScript pour gérer les opérations asynchrones. Il a été introduit dans ECMAScript 2017 (ES8) et construit sur les promesses de rendre le code asynchrone en JavaScript plus gérable et plus facile à lire. Async/wait offre une technique pour créer du code asynchrone avec une apparence et un comportement synchrones.
Une fonction asynchrone est définie par le mot clé « async ». La fonction asynchrone peut alors produire une promesse et utiliser le mot-clé « await » pour retarder l'exécution du code en attendant que la promesse soit remplie.
Un exemple est illustré ci-dessous :
Dans le code ci-dessus, " fetch " est une fonction asynchrone qui renvoie une promesse et le mot-clé " await " est utilisé pour attendre la résolution de la promesse avant d'analyser les données JSON.
L'utilisation de async/wait rend votre code plus facile à comprendre, à maintenir et plus robuste. Et par rapport aux rappels et aux promesses, c'est un moyen plus moderne, plus clair et plus efficace d'écrire du code asynchrone.
Cela étant dit, il est crucial de noter que async/wait complète les promesses, et non les remplace. En termes simples, il s'agit d'une syntaxe différente pour effectuer la même opération. Il s'appuie toujours sur des promesses pour gérer le flux asynchrone en interne.
3. Fermetures
En JavaScript, les fonctions internes peuvent accéder aux variables et à la portée de leurs fonctions externes grâce à un concept clé appelé fermetures. Lorsqu'une fonction est définie à l'intérieur d'une autre fonction et que la fonction interne conserve l'accès aux variables et à la portée d'exécution de la fonction externe même après que la fonction externe a terminé son exécution, une fermeture est générée.
Considérez le code suivant :
Dans cet exemple, la variable x est accessible à la fonction interne innerFunction à partir de la portée de la fonction externe car elle est définie à l'intérieur de la fonction externe outerFunction . La fonction externe renvoie la fonction interne, qui est ensuite affectée à la variable myClosure. La fonction interne a toujours accès à la valeur de x et peut la renvoyer lorsqu'elle est appelée même lorsque l'exécution de la fonction externe est terminée.
Les fermetures en JavaScript sont couramment utilisées pour diverses tâches, notamment la création de variables privées, l'application de paradigmes de programmation fonctionnelle et la création de fermetures dans des boucles. En permettant aux fonctions de transporter des données avec elles, les fermetures peuvent également être utilisées pour créer un code robuste et expressif. Toujours en JavaScript, il peut être utilisé pour implémenter des modèles de programmation orientés objet.
Néanmoins, les fermetures peuvent également entraîner des fuites de mémoire si elles ne sont pas utilisées correctement, car la fonction interne continue de maintenir une référence à la variable et à la portée de la fonction externe et le ramasse-miettes est incapable de libérer la mémoire.
4. Héritage prototype
Contrairement au modèle d'héritage basé sur les classes utilisé dans des langages tels que Java et C #, JavaScript utilise un modèle d'héritage basé sur un prototype. En JavaScript, les objets héritent leurs propriétés et méthodes d'autres objets plutôt que de classes.
Chaque objet JavaScript possède une propriété interne appelée __proto__ (ou [[Prototype]]), qui pointe vers un objet différent appelé « objet prototype ». Lors de l'accès aux propriétés ou aux méthodes d'un objet, JavaScript détermine d'abord si l'objet lui-même a la propriété ou la méthode définie directement sur lui. Si ce n'est pas le cas, JavaScript vérifie l'objet prototype de l'objet et poursuit sa recherche dans la chaîne de prototypes jusqu'à ce qu'il trouve la propriété ou la méthode ou atteigne la fin de la chaîne.
Regardons l'exemple ci-dessous :
Vous remarquerez à partir du code ci-dessus que l'objet « chien » dans cet exemple hérite de l' attribut « mange » de « animal », son objet prototype, plutôt que de l'avoir spécifié directement dessus. C'est ainsi que fonctionne l'héritage prototypique. C'est un mécanisme dans lequel les objets peuvent hériter des propriétés et des méthodes d'autres objets.
Il est essentiel de noter ici que l'héritage dans ce contexte est dynamique et non statique, ce qui signifie que vous pouvez modifier l'objet prototype en ajoutant ou en supprimant des propriétés et des méthodes, et les objets qui en dérivent seront mis à jour pour refléter les modifications.
Bien que le paradigme de l'héritage basé sur les prototypes en JavaScript ait le potentiel d'être plus flexible et puissant que l'héritage basé sur les classes, il peut aussi être plus compliqué et difficile à comprendre. Pour utiliser et créer correctement des objets en JavaScript, il faut avoir une solide compréhension de l'héritage basé sur les prototypes.
5. Curry
Le currying en JavaScript est une technique qui permet l'application partielle d'une fonction en pré-remplissant certains de ses arguments. Cela permet aux appels de fonction d'être réutilisés et flexibles.
Considérons une fonction qui accepte les deux arguments x et y et renvoie leur total à titre d'exemple.
En utilisant des fermetures, nous pouvons transformer cette fonction en une fonction curry qui accepte l'argument restant.
Dans cette illustration, l'utilisation initiale de add(2) donne une nouvelle fonction qui accepte l'argument final, y. Étant donné que les valeurs x et y sont déjà définies sur 2 et 3, respectivement, lorsque add2(3) est appelé, le résultat est 5.
L'opérateur d'étalement et les fonctions fléchées peuvent également être utilisés pour réaliser le curry. Jetons un coup d'œil à un exemple ci-dessous :
Dans cette illustration, le premier appel à add(2) produit une nouvelle fonction fléchée qui ajoute x et y à tous les arguments restants, quel que soit leur nombre.
Le curry peut augmenter la réutilisabilité et la lisibilité du code tout en permettant aux appels de fonction d'être plus flexibles.
6. Fonctions d'ordre supérieur
Les fonctions d'ordre supérieur en JavaScript sont celles qui acceptent une ou plusieurs fonctions comme arguments et/ou renvoient une autre fonction comme sortie. Comme elles peuvent être utilisées comme n'importe quelle autre variable ou valeur, ces fonctions sont également appelées "fonctions de première classe". Le terme "ordre supérieur" indique un niveau d'abstraction plus élevé que la fonction JavaScript habituelle.
Voici quelques exemples de fonctions d'ordre supérieur :
je. Array.prototype.map() : cette fonction applique une fonction de rappel à chaque élément d'un tableau qu'elle reçoit en tant qu'argument, renvoyant un nouveau tableau avec les résultats.
ii. Array.prototype.filter() : cette fonction accepte une fonction de rappel comme argument et l'applique à chaque élément du tableau, renvoyant un nouveau tableau avec uniquement les éléments qui réussissent le test.
iii. Array.prototype.reduce() : cette fonction prend une fonction de rappel comme argument et l'applique à chaque élément d'un tableau, accumulant les résultats en une seule valeur.
iv. Array.prototype.forEach() : cette fonction est une méthode itérative et appelle une fois une fonction de rappel fournie pour chaque élément d'un tableau dans l'ordre d'index croissant.
v. setTimeout() : cette fonction accepte une fonction de rappel en tant qu'entrée et planifie son exécution pour une durée donnée dans le futur.
vi. Promise.then() : cette fonction accepte une fonction de rappel en tant qu'entrée et planifie son exécution lorsqu'une promesse est résolue.
Ces fonctions d'ordre supérieur offrent un mécanisme d'abstraction de la logique et des fonctionnalités en les transmettant sous forme de variables ou d'arguments, permettant un code plus adaptable et réutilisable. Par exemple, si vous souhaitez qu'un tableau de nombres ne renvoie que des nombres pairs, vous pouvez utiliser la méthode d'ordre supérieur filter().
La fonction filter() dans cet exemple reçoit une fonction anonyme en tant que rappel et l'utilise pour déterminer si chaque élément du tableau est pair avant de renvoyer uniquement les nombres pairs.
7. Générateurs
Il s'agit d'un type spécial de fonction en JavaScript qui permet des pauses et des redémarrages d'exécution. Ils sont utiles lorsque vous travaillez avec des itérateurs et des programmes asynchrones car ils vous permettent de construire une séquence de valeurs au fil du temps.
Une fonction génératrice est définie à l'aide du mot-clé function* et utilise le mot-clé yield pour interrompre l'exécution et renvoyer une valeur. Lorsque la fonction générateur est invoquée, elle produit un objet itérateur qui peut être utilisé pour contrôler l'exécution du générateur.
Supposons que nous voulions créer une fonction génératrice qui renvoie le nombre suivant dans la suite de Fibonacci :
Dans l'exemple ci-dessus, le mot clé function* est utilisé pour déclarer la fonction génératrice fibonacci(). Il utilise le mot clé yield pour renvoyer la valeur actuelle de a et met à jour les valeurs de a et b à l'aide de l'affectation de déstructuration. La boucle while garantit que le générateur continuera à produire de nouvelles valeurs indéfiniment.
La fonction générateur, lorsqu'elle est invoquée, renvoie un objet itérateur qui peut être utilisé pour contrôler l'exécution du générateur. La méthode next() est utilisée pour reprendre l'exécution et renvoyer la valeur suivante.
De grands ensembles de données, du code asynchrone, des itérateurs et des séquences infinies peuvent tous être implémentés à l'aide de générateurs. Sans avoir à charger toutes les données en mémoire d'un coup, ils permettent de générer une succession de valeurs dans le temps.
8. WeakMaps et WeakSets
Semblable à une carte en JavaScript, une WeakMap est un type de collecte de données qui vous permet de stocker des paires clé-valeur. La distinction importante est que les clés d'un WeakMap sont faiblement référencées, ce qui signifie qu'elles peuvent être ramassées s'il n'existe aucune autre référence à celles-ci. WeakMap peut ainsi être utilisé pour stocker des données que vous ne souhaitez pas conserver en mémoire si elles ne sont plus utilisées.
D'un autre côté, un WeakSet est similaire à un Set mais présente le même comportement de référencement faible pour ses composants. Cela signifie que s'il n'y a pas d'autres références à un élément dans un WeakSet, il peut être ramassé.
Voici un exemple d'utilisation d'un WeakMap en JavaScript :
Dans l'exemple ci-dessus, nous avons créé une WeakMap et stocké une paire clé-valeur avec un objet servant de clé. Nous utilisons ensuite l'objet comme clé pour obtenir la valeur. La paire clé-valeur est également éliminée de WeakMap lorsque nous définissons l'objet sur null, ce qui le rend adapté à la récupération de place.
Un exemple d'un WeakSet, cependant, est montré ci-dessous :
Dans cet exemple, deux objets sont ajoutés à un WeakSet qui a été créé. La méthode has() est ensuite utilisée pour déterminer si un certain objet est présent dans l'ensemble. Le premier objet est retiré du WeakSet et est éligible pour la récupération de place une fois que nous l'avons défini sur null.
WeakMap et WeakSet sont utiles pour gérer l'utilisation de la mémoire JavaScript car ils vous permettent de stocker des informations sans les stocker en mémoire de manière permanente.
9. Procurations
Les objets qui servent d'intermédiaires entre le code qui y accède et les objets sous-jacents qu'ils représentent sont appelés proxies. Ils vous permettent de modifier et d'intercepter les opérations effectuées sur l'objet sous-jacent, telles que les appels de méthode, les constructeurs et l'accès aux propriétés.
Le code suivant est un exemple de la façon dont un proxy peut être utilisé pour intercepter l'accès à la propriété :
Dans cet exemple, un objet appelé obj est enveloppé dans un objet Proxy. Pour gérer l'accès et l'affectation des propriétés, nous définissons deux fonctions "handler", " get " et " set ". Nous pouvons intercepter et modifier le comportement de l'objet sous-jacent à l'aide de ces fonctions. La fonction « get » sera appelée, un message sera consigné et la valeur de la propriété « name » de l'objet d'origine sera renvoyée lorsque nous accéderons à la propriété name de l'objet proxy.
Les proxys peuvent être utilisés à diverses fins, telles que :
- Implémentation d'accesseurs de propriété personnalisés
- Implémentation de l'invocation de méthode personnalisée
- Implémentation de constructeurs personnalisés
- Implémentation d'un comportement personnalisé pour les objets "virtuels"
- Implémentation d'un comportement personnalisé pour les objets existants
- Implémentation de la gestion personnalisée des erreurs
- Implémentation de fonctionnalités de sécurité personnalisées
10. Refléter l'API
Semblable à la façon dont vous utiliseriez les opérateurs et les fonctions intégrés de JavaScript, l'API JavaScript Reflect propose un certain nombre de méthodes qui vous permettent d'effectuer diverses actions sur des objets. La principale distinction est que les opérateurs et fonctions intégrés renvoient souvent le résultat de l'opération, tandis que les méthodes de l'API Reflect renvoient généralement un booléen indiquant le succès ou l'échec de l'opération.
Jetons un coup d'œil à l'exemple ci-dessous :
Dans cet exemple, la propriété "name" de l'objet obj est définie sur la valeur "John" à l'aide de la méthode Reflect.set(). Lorsque l'opération réussit, la méthode renvoie true.
Voici un autre exemple d'utilisation de l'API Reflect pour déterminer si un objet est extensible ou non :
Cet exemple montre comment vérifier l'extensibilité d'un objet à l'aide de la méthode Reflect.isExtensible(). En raison de sa nature extensible par défaut, il renvoie initialement true. Ensuite, nous utilisons Object.preventExtensions(obj) pour empêcher l'extension de l'objet. Ensuite, nous utilisons Reflect.isExtensible(obj) une fois de plus, qui renvoie false pour indiquer que l'objet n'est plus extensible.
L'API Reflect fournit un certain nombre de méthodes, telles que :
- Refléter.get()
- Refléter.set()
- Reflect.has()
- Reflect.deleteProperty()
- Reflect.defineProperty()
- Reflect.getOwnPropertyDescriptor()
- Reflect.getPrototypeOf()
- Reflect.setPrototypeOf()
- Reflect.preventExtensions()
- Reflect.isExtensible()
- Réfléchir.appliquer()
- Refléter.construct()
En conclusion, la maîtrise de JavaScript nécessite d'avoir une solide maîtrise d'un large éventail de concepts et de techniques. Les concepts abordés dans cet article, tels que les fermetures, les prototypes, les fonctions d'ordre supérieur ne sont que quelques-uns des nombreux concepts essentiels pour comprendre le fonctionnement de JavaScript et comment écrire un code efficace. De plus, comprendre comment utiliser des fonctionnalités modernes telles que Promises, async/await, WeakMap et WeakSet, Proxies et Reflect API, qui sont également abordées ici, peut vous aider à écrire un code JavaScript plus moderne et plus puissant. En prenant le temps de bien comprendre ces concepts et leur fonctionnement, vous pouvez devenir un développeur JavaScript plus compétent et plus confiant.
![Qu'est-ce qu'une liste liée, de toute façon? [Partie 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































