Les nouveaux objets Set et Map en javascript ES6
Beaucoup d’avancées ont été faites avec ES6 – voir mon article sur les nouvelles fonctionnalités en ES6 – mais prenons un petit moment pour examiner deux nouveaux constructeurs qui ont été introduits dans la spécification javascript ES6 j’ai nommé Set()
et Map()
Set
: L’objet Set vous permet de stocker des valeurs uniques de tout type.Map
: L’objet Map vous permet de stocker les paires clé-valeur et de mémoriser l’ordre d’insertion original des clés.
L’objectif de ces nouveaux constructeurs est de fournir des moyens plus faciles et plus efficaces de structurer et d’accéder aux données dans certains cas d’utilisation. Pour faire suite à mon article sur les méthodes de tableau javascript, nous examinerons ici le fonctionnement des ensembles (sets
) et des maps
et explorerons certaines des opérations qui peuvent être effectuées sur eux.
L’objet Set
en javascript ES6
La documentation MDN décrit l’objet Set comme suit :
Les objets
Set
sont des ensembles de valeurs. Il est possible d’itérer sur les éléments contenus dans l’objetSet
dans leur ordre d’insertion. Une valeur donnée ne peut apparaître qu’une seule fois parSet
.
L’objet JavaScript Set
se comporte de la même manière que l’objet mathématique Set
. Il permet l’ajout de valeurs distinctes et fournit des méthodes utiles sur son prototype. Ces méthodes comprennent l’ajout, la suppression et l’itération des éléments présents dans l’ensemble.
Comparaison des objets javascript Array
et Set
Un tableau, comme un ensemble, est une structure de données qui permet d’ajouter, de supprimer et de boucler des opérations sur ses éléments. Cependant, un tableau diffère d’un ensemble en ce sens qu’il permet l’addition de valeurs dupliquées et que ses opérations sont relativement plus lentes.
La recherche dans un tableau a une complexité temporelle linéaire de O(n), la même chose que l’insertion d’un élément au milieu d’un tableau. Cela signifie que le temps d’exécution de la recherche et de l’insertion d’éléments dans un tableau augmente à mesure que la taille du tableau augmente.
Les méthodes de tableau JavaScript Push
et Pop
ont un temps d’exécution de O(1) ce qui signifie que ces opérations auront un temps d’exécution constant quelle que soit la taille du tableau. Cependant, dans la pratique, l’opération Push est O(n) car les coûts de copie sont encourus lorsque de nouveaux emplacements de mémoire contigus sont alloués au réseau nouvellement formé.
En revanche, toutes les opérations d’insertion, de suppression et de recherche de Sets ont une durée de fonctionnement de seulement O(1).
Comment créer un ensemble (Set
) en javascript ?
Créons un ensemble :
const set = new Set(); console.log(set); // Set {}
Comment initialiser un ensemble (Set
) en javascript ?
Pour initialiser un ensemble, on peut passer un tableau de valeurs au constructeur de l’ensemble, cela va créer un ensemble avec ces valeurs :
const confectioneries = new Set(['oreo', 'marshmallow','oreo', 'kitkat', 'gingerbread']); console.log(confectioneries); // result: Set { 'oreo', 'marshmallow', 'kitkat', 'gingerbread' }
Dans l’extrait ci-dessus, la valeur en double “oreo” est discrètement supprimée de l’ensemble et seules les valeurs uniques sont renvoyées.
Comment ajouter un élément dans un ensemble (Set
) javascript ?
Nous pouvons ajouter plus d’éléments à un ensemble en utilisant la méthode add(). Cette méthode ajoute une nouvelle valeur à l’objet Set
et retourne le Set
. Une tentative d’ajout d’un élément dupliqué à l’objet Set
ne retournerait pas d’erreur, au lieu de cela, l’élément ne sera pas ajouté.
Prenons un exemple :
const confectioneries = new Set(['oreo', 'marshmallow', 'kitkat', 'oreo','gingerbread']); confectioneries.add('donut'); console.log(confectioneries); //_ log result: Set { 'oreo', 'marshmallow', 'kitkat', 'gingerbread', 'donut' } _ confectioneries.add('kitkat'); console.log(confectioneries); //_ log result: Set { 'oreo', 'marshmallow', 'kitkat', 'gingerbread', 'donut' } _
Comment supprimer un élément dans un ensemble (Set
) javascript ?
Avec les ensembles, nous pouvons supprimer des éléments en utilisant l’une ou l’autre de ces commandes :
delete()
clear()
Pour utiliser la méthode delete()
, la valeur à supprimer est transmise à la méthode. La méthode retournera une valeur booléenne vraie si la suppression a réussi et fausse si ce n’est pas le cas. Nous pouvons supprimer tous les éléments de l’objet Set en utilisant la méthode clear()
.
Essayons les deux méthodes dans cet exemple :
confectioneries.delete('kitkat'); console.log(confectioneries); //_ log result: Set { 'oreo', 'marshmallow', 'gingerbread', 'donut' }_ confectioneries.clear(); console.log(confectioneries); // log result: Set {}
Comment connaitre la taille d’un ensemble (Set
) en javascript ?
Nous pouvons obtenir la taille d’un ensemble en utilisant la propriété size
sur le prototype de l’ensemble. Ceci est similaire à la propriété length
pour les tableaux :
const confectioneries = new Set(['oreo', 'marshmallow', 'kitkat', 'oreo','gingerbread']); console.log(confectioneries.size); // log result: 5
Comment rechercher un élément parmi un ensemble (Set
) javascript ?
Il se peut que nous ayons besoin de savoir si un ensemble contient un élément particulier. Ceci peut être réalisé en utilisant la méthode has()
. La méthode has()
retourne true si l’élément est dans l’objet Set
, et false s’il ne l’est pas :
const confectioneries = new Set(['oreo', 'marshmallow', 'kitkat', 'oreo','gingerbread']); console.log(confectioneries.has('marshmallow')); // log result: true
Comment recupérer les éléments d’un ensemble (Set
) javascript ?
Nous pouvons retourner les éléments d’un objet Set
dans le même ordre d’insertion en utilisant la méthode values()
. Cette méthode retourne un nouvel objet setIterator
. Une méthode similaire pour retourner les éléments d’un ensemble est la méthode keys()
:
const confectioneries = new Set(['oreo', 'marshmallow', 'kitkat', 'oreo','gingerbread', 'donut']); console.log(confectioneries.values()); // _log result: _[_Set Iterator] { 'oreo', 'marshmallow', 'kitkat', 'gingerbread', 'donut' }_ console.log(confectioneries.keys()); //_ log result: _[_Set Iterator] { 'oreo', 'marshmallow', 'kitkat', 'gingerbread', 'donut' }_
L’objet setIterator
est un objet Iterator
car il implémente les protocoles Iteratable
et Iterator
. Le protocole Iterable
spécifie un moyen d’itération à travers un ensemble de valeurs en utilisant des constructions en boucle. Il permet également d’itérer les valeurs à l’aide de la méthode next()
. Quand nous appelons next()
sur un objet setIterator
, nous obtenons la valeur suivante dans l’itération et une false si toutes les valeurs du Set
ont été itérées :
const confectioneries = new Set(['oreo', 'marshmallow', 'kitkat', 'oreo','gingerbread', 'donut']); let iterator = confectioneries.values(); console.log( iterator.next()); // _{ value: 'oreo', done: false } _ console.log( iterator.next()); // _{ value: 'marshmallow', done: false } _ console.log( iterator.next()); //_ { value: 'kitkat', done: false } _ console.log( iterator.next()); //_ { value: 'gingerbread', done: false } _ console.log( iterator.next()); //_ { value: 'donut', done: false } _ console.log( iterator.next()); // _{ value: undefined, done: true }_
Puisque les ensembles implémentent le protocole Itérable, les constructions de boucle telles que for…of peuvent être utilisées comme indiqué ci-dessous :
for (let confectionery of confectioneries) { console.log(confectionery); } /_ _console.log() result oreo marshmallow kitkat gingerbread donut __/
L’objet WeakSet
en javascript
Les WeakSets
offrent une flexibilité supplémentaire lors de l’utilisation de la structure de données Set
. Ils sont différents des Sets réguliers en ce sens qu’ils n’acceptent que les objets et ne sont pas itérables ; ils ne peuvent pas être bouclés, et n’ont pas de méthode clear
(). Comment, alors, apportent-ils une flexibilité supplémentaire ? Je vais vous dire ça dans un instant.
Nous pouvons créer un objet WeakSet
en utilisant le constructeur WeakSet
:
let user1 = {name: 'user 1', email: 'user1@example.com'}; let user2 = {name: 'user 2', email: 'user2@example.com'}; let user3 = {name: 'user 3', email: 'user3@example.com'}; const users = new WeakSet([user1, user2, user3]);
Le code ci-dessus crée un nouvel objet WeakSet
, ajoutant des éléments autres que des objets renvoie un TypeError
:
users.add('user 4'); console.log(users); // TypeError: Invalid value used in weak set
Comme les WeakSets
n’ont pas de méthode clear()
, les objets ne peuvent être supprimés qu’en les mettant à null
. Cela fonctionne parce que les algorithmes du ramasse-miette de JavaScript libéreront automatiquement la mémoire allouée à l’objet nul, le supprimant ainsi du WeakSet.
C’est merveilleux parce que les objets WeakSets réglés sur null sont ramassés à la poubelle pendant que le programme est encore en cours d’exécution, ce qui réduit la consommation de mémoire et empêche les fuites, surtout lorsqu’il s’agit d’énormes quantités de données générées de façon asynchrone.
Cette fonction vous permet d’écrire des solutions légères aux problèmes de programmation sans avoir à vous soucier des détails de la gestion de la mémoire.
L’objet Map
en javascript ES6
Les Maps
Javascript sont des objets conçus pour stocker et récupérer efficacement des éléments en fonction d’une clé unique pour chaque élément. Une Map
stocke des paires clé-valeur où les clés et les valeurs peuvent être soit des valeurs primitives, soit des objets, soit les deux.
La documentation de MDN décrit l’objet Map comme suit :
Un objet
Map
permet de retrouver ses éléments dans leur ordre d’insertion. Par exemple, une bouclefor...of
renverra un tableau de[clé, valeur]
pour chaque itération.
Comment créer une Map
en javascript ?
Comme les Sets
, les Maps
sont faciles à créer. Créez une Map
à l’aide du constructeur Map
:
const users = new Map(); console.log(users); // Map {}
Comment ajouter un élément dans Map
javascript ?
Les paires clé-valeur sont ajoutées à une Map
à l’aide de la méthode set()
. Cette méthode prend en compte deux arguments, le premier étant la clé et le second, la valeur, qui est référencée par la clé :
users.set('John Doe', { email: 'johndoe@example.com', }); users.set('Jane Doe', { email: 'janedoe@example.com', }); console.log(users); /__ console.log result Map { 'John Doe' => { email: 'johndoe@example.com'}, 'Jane Doe' => { email: 'janedoe@example.com'} } __/
Contrairement aux Sets
qui suppriment les clés dupliquées, Maps
met à jour la valeur attachée à cette clé :
users.set('John Doe', { email: 'johndoe477@example.com', }); console.log(users); /__ console.log result Map { 'John Doe' => {email: 'johndoe477@example.com'}, 'Jane Doe' => { email: 'janedoe@example.com'} } __/
Lorsque vous exécutez l’exemple ci-dessus, le courriel de John DoeUntel sera remplacé proprement. Cool
Comment supprimer un élément dans Map
javascript ?
Comme pour les ensembles, les combinaisons clé-valeur peuvent être supprimées à l’aide de la méthode delete()
. La clé à effacer est transmise à la méthode delete()
comme indiqué ci-dessous :
users.delete('Jane Doe');
Les Maps
ont aussi une méthode clear()
, qui supprime toutes les paires clé-valeur de l’objet Map
:
users.clear(); console.log(users); // Map {}
Comment rechercher un élément parmi une Map
javascript ?
Les Maps
ont aussi une méthode has()
qui vérifie si une clé existe dans une Map
. Cette méthode retournera true si la clé est dans la Map
et false si elle ne l’est pas :
let users = new Map(); users.set('John Doe', { email: 'johndoe@example.com', }); users.set('Jane Doe', { email: 'janedoe@example.com', }); console.log(users.has('John Doe')); // true
Comment récupérer les éléments d’une Map
javascript ?
La valeur d’une clé dans un objet Map
peut être obtenue en utilisant la méthode get
sur le prototype Map
:
console.log(users.get('Jane Doe'); // { email: 'janedoe@example.com' }
Il est possible d’obtenir toutes les clés et valeurs d’un objet Map
en utilisant les méthodes keys()
et values()
respectivement. Ces deux méthodes retournent un nouvel objet MapIterator
qui a une méthode next()
utilisable pour boucler les éléments de la Map
:
let userKeys = users.keys(); console.log(userKeys.next()); // { value: 'John Doe', done: false } let userValues = users.values(); console.log(userValues.next()); // _{ value: { email: 'johndoe@example.com' }
Comme pour les Sets
, les boucles telles que for…of
et forEach()
peuvent être utilisées pour itérer à travers les éléments de la Map
:
for (let user of users) { console.log('[for...of]: ', user); } /_ Log result _[_for...of]: _[_ 'John Doe', { email: 'johndoe@example.com' } ] _[_for...of]: _[___ 'Jane Doe', { email: 'janedoe@example.com' } ] _/ users.forEach((value, key) => console.log('[__forEach()]: ', key, value)); /*_ Log result [__forEach()]: John Doe { email: 'johndoe@example.com' } _[_forEach()]: Jane Doe { email: 'janedoe@example.com' } *_/
L’objet WeakMap
en javascript
Comme pour les WeakSets
, les WeakMaps
diffèrent des objets Maps
normaux. Les WeakMaps
n’acceptent que les objets comme clés, ne sont pas itérables et n’ont pas de méthode clear()
.
Un constructeur
WeakMap
est utilisé pour créer un objetWeakMap
.
Prenons un exemple :
let users = new WeakMap(); const user1 = { name: 'John Doe', }; const user2 = { name: 'Jane Doe', }; users.set(user1, { email: 'johndoe@example.com', }); users.set(user2, { email: 'janedoe@example.com', });
Comme avec WeakSets
, mettre la clé d’un objet WeakMap
à null va implicitement mettre cet objet dans le ramasse-miettes :
user1 = null;
Ceci a les mêmes avantages qu’avec les WeakSets
pour faciliter la gestion de la mémoire.
Conclusion
Dans cet article, nous avons examiné les Sets
et les Maps
et la façon dont ils traitent les éléments uniques et les paires clé-valeur respectivement. Ces structures de données sont très utiles et permettent de structurer et d’accéder plus facilement et plus efficacement aux données dans certains cas d’utilisation.
Des modifications spéciales telles que WeakSets
et WeakMaps
offrent plus d’options pour le développeur et sont pratiques pour la gestion de la mémoire.
Si vous avez aimé cet article (ou si vous y voyez quelques coquilles) n’hésitez pas à me mettre un petit commentaire