104 votes

Quelle est la différence entre ES6 Map et WeakMap ?

Recherche este y este Dans les pages MDN, il semble que la seule différence entre Maps et WeakMaps soit l'absence de la propriété "size" pour WeakMaps. Mais est-ce vrai ? Quelle est la différence entre les deux ?

109voto

KShirish Points 50

Ils se comportent tous deux différemment lorsqu'un objet référencé par leurs clés/valeurs est supprimé. Prenons l'exemple de code ci-dessous :

var map = new Map();
var weakmap = new WeakMap();

(function(){
    var a = {x: 12};
    var b = {y: 12};

    map.set(a, 1);
    weakmap.set(b, 2);
})()

Le IIFE ci-dessus est exécuté, il n'y a aucun moyen de référencer {x: 12} y {y: 12} plus. Le collecteur d'ordures va de l'avant et supprime le pointeur de la clé b de "WeakMap" et supprime également {y: 12} de mémoire. Mais dans le cas de "Map", le ramasseur d'ordures ne supprime pas un pointeur de "Map" et ne supprime pas non plus les éléments suivants {x: 12} de mémoire.

Résumé : WeakMap permet au ramasseur d'ordures d'effectuer sa tâche mais pas à Map.

Références : http://qnimate.com/difference-between-map-and-weakmap-in-javascript/

86voto

Rax Wunter Points 23

Peut-être que la prochaine explication sera plus claire pour quelqu'un.

var k1 = {a: 1};
var k2 = {b: 2};

var map = new Map();
var wm = new WeakMap();

map.set(k1, 'k1');
wm.set(k2, 'k2');

k1 = null;
map.forEach(function (val, key) {
    console.log(key, val); // k1 {a: 1}
});

k2 = null;
wm.get(k2); // undefined

Comme vous le voyez, après avoir retiré k1 de la mémoire, nous pouvons toujours y accéder dans la carte. En même temps, le fait de retirer k2 de WeakMap l'enlève de wm ainsi que par référence.

C'est pourquoi WeakMap n'a pas de méthodes énumérables comme forEach, parce qu'il n'existe pas de liste de clés WeakMap, ce sont juste des références à d'autres objets.

56voto

Bergi Points 104242

En à la même page, section " Pourquoi Faible Une carte ? " :

Le programmeur JavaScript expérimenté remarquera que cette API pourrait être implémentée en JavaScript avec deux tableaux (un pour les clés, un pour les valeurs) partagés par les 4 méthodes de l'API. Une telle implémentation aurait deux inconvénients principaux. Le premier est une recherche de O(n) (n étant le nombre de clés dans la carte). Le second est un problème de fuite de mémoire. Avec des cartes écrites manuellement, le tableau de clés conserverait les références à objets clés, les empêchant d'être ramassés. Dans les WeakMaps natives, les références aux objets clés sont conservées. "faiblement" ce qui signifie qu'ils n'empêchent pas la collecte des déchets au cas où il n'y aurait pas autre référence à l'objet.

Comme les références sont faibles, les clés WeakMap ne sont pas énumérables. (c'est-à-dire qu'il n'existe pas de méthode permettant d'obtenir une liste des clés). Si elles l'étaient la liste dépendrait de l'état du ramassage des déchets, ce qui introduirait non-déterminisme.

[Et c'est pourquoi ils n'ont pas size également la propriété]

Si vous voulez avoir une liste de clés, vous devez la tenir à jour vous-même. Il existe également une ECMAScript proposition visant à introduire des ensembles et des cartes simples qui n'utiliseraient pas de faibles et qui seraient énumérables.

- qui serait le "normal" Map s . Non mentionné à MDN, mais dans le proposition d'harmonie Ceux-ci ont également items , keys y values et mettre en œuvre les méthodes du générateur Iterator interface .

36voto

Trevor Dixon Points 6384

Une autre différence (source : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap ):

Les clés de WeakMaps sont uniquement de type Object. Les types de données primitifs comme ne sont pas autorisés (par exemple, un symbole ne peut pas être une clé de WeakMap).

Une chaîne de caractères, un nombre ou un booléen ne peut pas non plus être utilisé comme un WeakMap clé. A Map puede utiliser des valeurs primitives pour les clés.

w = new WeakMap;
w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key

m = new Map
m.set('a', 'b'); // Works

10voto

Avadhut Thorat Points 21

En Javascript.info

Carte -- Si nous utilisons un objet comme clé dans une Map ordinaire, alors tant que la Map existe, cet objet existe également. Il occupe de la mémoire et peut ne pas être récupéré par les ordures.

let john = { name: "John" };
let array = [ john ];
john = null; // overwrite the reference

// john is stored inside the array, so it won't be garbage-collected
// we can get it as array[0]

De la même manière, si nous utilisons un objet comme clé dans une Map ordinaire, alors tant que la Map existe, cet objet existe également. Il occupe de la mémoire et peut ne pas être récupéré par les ordures ménagères.

let john = { name: "John" };
let map = new Map();
map.set(john, "...");
john = null; // overwrite the reference

// john is stored inside the map,
// we can get it by using map.keys()

WeakMap -- Maintenant, si nous utilisons un objet comme clé dans cette carte, et qu'il n'y a pas d'autres références à cet objet - il sera supprimé de la mémoire (et de la carte) automatiquement.

let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // overwrite the reference

// john is removed from memory!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X