Fermer

avril 6, 2018

Utilisation de Map, Set, WeakMap, WeakSet –


Cet article examine quatre nouvelles collections ES6 et les avantages qu'elles procurent.

La plupart des principaux langages de programmation possèdent plusieurs types de collections de données. Python a des listes, des tuples et des dictionnaires. Java a des listes, des ensembles, des cartes, des files d'attente. Ruby a des hachages et des tableaux. JavaScript, jusqu'à présent, n'avait que des tableaux. Les objets et les tableaux étaient les chevaux de bataille de JavaScript. ES6 introduit quatre nouvelles structures de données qui ajouteront de la puissance et de l'expressivité à la langue: Carte Ensemble WeakSet et WeakMap . [19659003] Recherche de la HashMap JavaScript

HashMaps, dictionnaires et hash sont plusieurs façons par lesquelles différents langages de programmation stockent des paires clé / valeur, et ces structures de données sont optimisées pour une récupération rapide.

Dans ES5, les objets JavaScript juste collections arbitraires de propriétés avec des clés et des valeurs – peuvent simuler des hachages, mais il y a plusieurs inconvénients à utiliser des objets comme des hachages

Downside # 1: Les clés doivent être des chaînes dans ES5

Les clés doivent être des chaînes, ce qui limite leur capacité à servir de collection de paires clé / valeur de différents types de données. Vous pouvez, bien sûr, contraindre / stringifier d'autres types de données en chaînes, mais cela ajoute un travail supplémentaire.

Downside # 2: Les objets ne sont pas intrinsèquement itératifs

Les objets n'ont pas été conçus pour être utilisés comme collections. Résultat, il n'existe aucun moyen efficace de déterminer le nombre de propriétés d'un objet. (Voir, par exemple, Object.keys est lent ). Lorsque vous bouclez sur les propriétés d'un objet, vous obtenez également ses propriétés de prototype. Vous pouvez ajouter la propriété itérable à tous les objets, mais tous les objets ne doivent pas être utilisés comme collections. Vous pouvez utiliser la pour ... dans la boucle et la méthode hasOwnProperty () mais ce n'est qu'une solution de contournement. Lorsque vous bouclez sur les propriétés d'un objet, les propriétés ne seront pas nécessairement récupérées dans le même ordre que celui dans lequel elles ont été insérées

Downside # 3: Défis avec collisions de méthode intégrées

Les objets ont des méthodes intégrées comme constructeur toString et valeurDe . Si l'un d'entre eux a été ajouté en tant que propriété, cela pourrait provoquer des collisions. Vous pouvez utiliser Object.create (null) pour créer un objet nu (qui n'hérite pas de object.prototype ), mais, encore une fois, ce n'est qu'une solution de contournement. [19659005] ES6 inclut de nouveaux types de données de collection, il n'est plus nécessaire d'utiliser des objets et de vivre avec leurs inconvénients.

Utiliser les collections de cartes ES6

Map est la première structure de données / collection examiner. Les cartes sont des collections de clés et de valeurs de tout type. Il est facile de créer de nouvelles cartes, d'ajouter / de supprimer des valeurs, de boucler des clés / valeurs et de déterminer efficacement leur taille. Voici les méthodes cruciales:

Créer une carte et utiliser des méthodes communes

 const map = new Map (); // Créer une nouvelle carte
map.set ('hobby', 'cyclisme'); // Définit une paire de valeurs de clé

const foods = {dîner: 'Curry', déjeuner: 'Sandwich', petit déjeuner: 'Oeufs'}; // Nouvel objet
const normalfoods = {}; // Nouvel objet

map.set (aliments normaux, aliments); // Définit deux objets comme paire de valeurs de clé

pour (const [key, value] de la carte) {
  console.log (`$ {clé} = $ {valeur}`); // passe-temps = cyclisme [object Object] = [object Object]
}

map.forEach ((valeur, clé) => {
  console.log (`$ {clé} = $ {valeur}`);
}, carte) // passe-temps = cyclisme [object Object] = [object Object]

map.clear (); // Efface les paires de valeurs clés
console.log (map.size === 0); // Vrai

Exécutez cet exemple sur JSBin

Utilisation de la collection Set

Les ensembles sont des listes ordonnées de valeurs qui ne contiennent pas de doublons. Au lieu d'être indexés comme des tableaux, les ensembles sont accessibles en utilisant des clés. Les ensembles existent déjà dans Java Ruby Python et beaucoup d'autres langues. Une différence entre les ES6 Sets et ceux dans d'autres langues est que l'ordre est important dans ES6 (ce qui n'est pas le cas dans de nombreuses autres langues). Voici les principales méthodes Set:

 const planetsOrderFromSun = new Set ();
planetsOrderFromSun.add ('Mercury');
planetsOrderFromSun.add ('Venus'). add ('Terre'). add ('Mars'); // Méthode chaînable
console.log (planetsOrderFromSun.has ('Earth')); // Vrai

planetsOrderFromSun.delete ('Mars');
console.log (planetsOrderFromSun.has ('Mars')); // Faux

pour (const x de planetsOrderFromSun) {
  console.log (x); // Même ordre dans out - Mercure Venus Earth
}
console.log (planetsOrderFromSun.size); // 3

planetsOrderFromSun.add ('Venus'); // Essayer d'ajouter un doublon
console.log (planetsOrderFromSun.size); // Toujours 3, n'a pas ajouté le doublon

planetsOrderFromSun.clear ();
console.log (planetsOrderFromSun.size); // 0

Exécutez cet exemple sur JSBin

Collection faible, mémoire et collection de place

La récupération de place JavaScript est une forme de gestion de mémoire dans laquelle les objets qui ne sont plus référencés sont automatiquement supprimés et leurs ressources récupérées.

Les références et de Set aux objets sont fortement conservées et ne permettent pas la récupération de place. Cela peut coûter cher si les maps / sets font référence à de gros objets qui ne sont plus nécessaires, comme les éléments DOM qui ont déjà été supprimés du DOM.

Pour remédier à cela, ES6 introduit deux nouvelles collections faibles appelées WeakMap et WeakSet . Ces collections ES6 sont 'faibles' car elles permettent d'effacer de la mémoire les objets qui ne doivent plus être effacés de la mémoire.

WeakMap

WeakMap est la troisième des nouvelles collections ES6 que nous couvrons. WeakMaps sont similaires aux cartes normales mais avec moins de méthodes et la différence mentionnée ci-dessus en ce qui concerne la collecte des ordures

 const aboutAuthor = new WeakMap (); // Créer un nouveau WeakMap
const currentAge = {}; // la clé doit être un objet
const currentCity = {}; // les clés doivent être un objet

aboutAuthor.set (currentAge, 30); // Définir les valeurs clés
aboutAuthor.set (currentCity, 'Denver'); // Les valeurs clés peuvent être de différents types de données

console.log (aboutAuthor.has (currentCity)); // Teste si WeakMap a une clé

aboutAuthor.delete (currentAge); // Supprimer une clé

Exécuter cet exemple sur JSBin

Les cas d'utilisation

WeakMaps ont plusieurs cas d'utilisation populaires . Ils peuvent être utilisés pour garder les données privées d'un objet privé, et ils peuvent également être utilisés pour garder trace des noeuds / objets DOM

Cas d'utilisation de données privées

L'exemple suivant provient de JavaScript expert Nicholas C. Zakas :

 var Personne = (fonction () {
  var privateData = nouveau WeakMap ();

  function Personne (nom) {
    privateData.set (this, {nom: nom});
  }

  Person.prototype.getName = function () {
    return privateData.get (this) .name;
  }

  retourner la personne;
} ());

L'utilisation d'une [WeakMap] simplifie le processus de confidentialité des données d'un objet. Il est possible de référencer l'objet Person mais l'accès à la propriété privée privateDataWeakMap n'est pas autorisé sans l'instance Person spécifique.

Les nœuds DOM utilisent le cas

Le projet Google Polymer utilise WeakMaps dans un morceau de code appelé PositionWalker.

PositionWalker conserve la trace d'une position dans un sous-arbre DOM, comme un nœud courant et un décalage dans ce nœud.

WeakMap est utilisé pour assurer le suivi des modifications, des suppressions et des modifications du nœud DOM:

 _makeClone () {
  this._containerClone = this.container.cloneNode (true);
  this._cloneToNodes = nouveau WeakMap ();
  this._nodesToClones = nouveau WeakMap ();

  ...

  Soit n = this.container;
  let c = this._containerClone;

  // trouve le clone de currentNode
  while (n! == null) {
    if (n === this.currentNode) {
    this._currentNodeClone = c;
    }
    this._cloneToNodes.set (c, n);
    this._nodesToClones.set (n, c);

    n = iterator.nextNode ();
    c = cloneIterator.nextNode ();
  }
}

WeakSet

WeakSets sont des ensembles de collections dont les éléments peuvent être collectés lorsque les objets qu'ils référencent ne sont plus nécessaires. WeakSets n'autorise pas l'itération. Leurs cas d'utilisation sont plutôt limités (pour l'instant, au moins). La plupart des premiers adeptes disent que WeakSets peut être utilisé pour marquer des objets sans les mutater . ES6-Features.org a un exemple d'ajout et de suppression d'éléments d'un WeakSet afin de savoir si les objets ont été marqués ou non:

 let isMarked = new WeakSet ()
let attachedData = nouveau WeakMap ()

classe d'exportation Node {
    constructeur (id) {this.id = id}
    mark () {isMarked.add (this)}
    unmark () {isMarked.delete (this)}
    marqué () {return isMarked.has (this)}
    définir des données (données) {attachedData.set (this, data)}
    get data () {return attachedData.get (this)}
}

laissez foo = new Node ("foo")

JSON.stringify (foo) === '{"id": "foo"}'
foo.mark ()
foo.data = "barre"
foo.data === "barre"
JSON.stringify (foo) === '{"id": "foo"}'

isMarked.has (toto) === vrai
attachedData.has (foo) === true
foo = null / * supprime seulement la référence à foo * /
attachedData.has (foo) === false
isMarked.has (foo) === faux

Carte Toutes les choses? Enregistrements vs collections ES6

Les cartes et les ensembles sont de nouvelles collections ES6 de paires clé / valeur. Cela dit, les objets JavaScript peuvent toujours être utilisés comme collections dans de nombreuses situations. Pas besoin de passer aux nouvelles collections ES6 sauf si la situation l'exige.

MDN a une belle liste de questions pour déterminer quand utiliser un objet ou une collection de clés:

  • Habituellement inconnu jusqu'à l'exécution, et avez-vous besoin de les rechercher dynamiquement?
  • Toutes les valeurs ont-elles le même type et peuvent-elles être utilisées de façon interchangeable?
  • Avez-vous besoin de clés qui ne soient pas des chaînes? les paires clé-valeur sont souvent ajoutées ou supprimées?
  • Avez-vous une quantité arbitraire (changeant facilement) de paires clé-valeur?
  • La collection est-elle itératie?

Nouvelles collections ES6 Les collections JavaScript ont déjà été assez limitées, mais cela a été corrigé avec ES6. Ces nouvelles collections ES6 ajouteront de la puissance et de la flexibilité au langage, tout en simplifiant la tâche des développeurs JavaScript qui les adoptent.

Cet article fait partie de la série de développement web de Microsoft tech evangelists et DevelopIntelligence sur l'apprentissage JavaScript pratique, les projets open-source et les meilleures pratiques d'interopérabilité, notamment le navigateur Microsoft Edge et le nouveau moteur de rendu EdgeHTML . DevelopIntelligence propose Formation JavaScript et Réagir Formation Cours à travers appendTo leur site web dédié au blog et au cours.

Nous encourageons vous tester sur les navigateurs et les périphériques, y compris Microsoft Edge – le navigateur par défaut pour Windows 10 – avec des outils gratuits sur dev.microsoftedge.com y compris le EdgeHTML issue tracker où vous pouvez signaler ou recherchez des problèmes EdgeHTML, tels que des problèmes de rendu de site ou de conformité aux normes. Aussi, visitez le blog Edge pour rester informé et mis à jour par les développeurs et les experts de Microsoft.




Source link