Wat is het verschil tussen ES6 Map en WeakMap?

Zoek diten dezeMDN-pagina’s lijkt het enige verschil tussen Maps en WeakMaps een ontbrekende “size”-eigenschap voor WeakMaps te zijn. Maar is dit waar? Wat is het verschil tussen beide?


Antwoord 1, autoriteit 100%

Ze gedragen zich allebei anders wanneer een object waarnaar wordt verwezen door hun sleutels/waarden wordt verwijderd. Laten we de onderstaande voorbeeldcode nemen:

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);
})()

De bovenstaande IIFE wordt uitgevoerd, we kunnen op geen enkele manier meer verwijzen naar {x: 12}en {y: 12}. Garbage Collector gaat door en verwijdert de key b-aanwijzer uit “WeakMap” en verwijdert ook {y: 12}uit het geheugen. Maar in het geval van “Map”, verwijdert de garbage collector geen aanwijzer uit “Map” en verwijdert ook {x: 12}niet uit het geheugen.

Samenvatting: Met WeakMap kan de vuilnisman zijn taak doen, maar niet met Map.

Referenties: http://qnimate.com/difference-between-map-and- zwakke kaart-in-javascript/


Antwoord 2, autoriteit 79%

Misschien is de volgende uitleg voor iemand duidelijker.

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

Zoals je ziet, hebben we na het verwijderen van de k1-sleutel uit het geheugen nog steeds toegang tot deze op de kaart. Tegelijkertijd verwijdert het verwijderen van de k2-sleutel van WeakMap deze ook uit wmdoor middel van verwijzing.

Daarom heeft WeakMap geen opsombare methoden zoals forEach, omdat er niet zoiets bestaat als een lijst met WeakMap-sleutels, het zijn slechts verwijzingen naar andere objecten.


Antwoord 3, autoriteit 52%

Van dezelfde pagina, sectie ” Waarom zwakkekaart?:

De ervaren JavaScript-programmeur zal merken dat deze API kan:
worden geïmplementeerd in JavaScript met twee arrays (een voor sleutels, een voor
waarden) gedeeld door de 4 API-methoden. Een dergelijke implementatie zou hebben
twee belangrijke ongemakken. De eerste is een O(n)-zoekopdracht (n is de
aantal sleutels op de kaart). De tweede is een geheugenlekprobleem.
Met handmatig geschreven kaarten zou de array van sleutels verwijzingen naar . behouden
belangrijke objecten, zodat ze niet bij het afval kunnen worden verzameld. in eigen taal
WeakMaps, verwijzingen naar belangrijke objecten worden “zwak”gehouden, wat betekent:
dat ze het ophalen van huisvuil niet verhinderen voor het geval dat er niet zou zijn
andere verwijzing naar het object.

Omdat referenties zwak zijn, zijn WeakMap-sleutels niet opsombaar
(d.w.z. er is geen methode die u een lijst met sleutels geeft). Als ze waren,
de lijst zou afhangen van de staat van vuilnisophaling, introducerend:
niet-determinisme.

[En daarom hebben ze ook geen eigenschap size]

Als u een lijst met sleutels wilt, moet u:
zelf onderhouden. Er is ook een ECMAScript
voorstel

gericht op het introduceren van eenvoudige sets en kaarten die geen zwak zouden gebruiken
referenties en zou opsombaar zijn.

‐ wat de “normale” Maps. Niet genoemd op MDN, maar in het harmonievoorstelhebben die ook items, keysen valuesgeneratormethoden en implementeer de Iterator-interface.


Antwoord 4, autoriteit 34%

Nog een verschil (bron: https://developer .mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap):

Sleutels van WeakMaps zijn van het type Alleen object. Primitieve gegevenstypen als
sleutels zijn niet toegestaan ​​(een symbool kan bijvoorbeeld geen WeakMap-sleutel zijn).

Noch kan een tekenreeks, getal of boolean worden gebruikt als een WeakMap-sleutel. Een Mapkanprimitieve waarden voor sleutels gebruiken.

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

Antwoord 5, autoriteit 8%

Van Javascript.info

Kaart— Als we een object gebruiken als de sleutel in een gewone kaart, dan bestaat de kaart ook, terwijl de kaart bestaat. Het neemt geheugen in beslag en mag niet als afval worden verzameld.

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]

Net als dat, als we een object als sleutel gebruiken in een gewone kaart, dan bestaat de kaart ook, terwijl de kaart bestaat. Het neemt geheugen in beslag en wordt mogelijk niet verzameld

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— Als we nu een object als sleutel gebruiken en er zijn geen andere verwijzingen naar dat object, wordt het automatisch uit het geheugen (en van de kaart) verwijderd.

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

Antwoord 6, autoriteit 4%

WeakMap-sleutels moeten objecten zijn, geen primitieve waarden.

let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "ok"); // works fine (object key)
// can't use a string as the key
weakMap.set("test", "Not ok"); // Error, because "test" is not an object

Waarom????

Laten we onderstaand voorbeeld bekijken.

let user = { name: "User" };
let map = new Map();
map.set(user, "...");
user = null; // overwrite the reference
// 'user' is stored inside the map,
// We can get it by using map.keys()

Als we een object gebruiken als de sleutel in een gewone Map, terwijl de
Mapbestaat, dat object bestaat ook. Het neemt het geheugen in beslag en kan
niet worden ingezameld.

WeakMapis in dit opzicht fundamenteel anders. Dat doet het niet
voorkom het verzamelen van afval van belangrijke objecten.

let user = { name: "User" };
let weakMap = new WeakMap();
weakMap.set(user, "...");
user = null; // overwrite the reference
// 'user' is removed from memory!

als we een object gebruiken als de sleutel erin, en er zijn geen andere
verwijzingen naar dat object – het wordt uit het geheugen verwijderd (en uit
de kaart) automatisch.

WeakMapondersteunt geeniteratie en methoden keys(), values(), entries (), dus er is geen manier om alle sleutels of waarden eruit te halen.

WeakMap heeft alleen de volgende methoden:

  • weakMap.get(key)
  • weakMap.set(sleutel, waarde)
  • weakMap.delete(key)
  • weakMap.has(key)

Dat is duidelijk, alsof een object alle andere referenties heeft verloren (zoals ‘gebruiker’ in de bovenstaande code), dan moet het automatisch worden verwijderd. Maar technisch gezien is het niet precies gespecificeerd wanneer het opruimen plaatsvindt.

De JavaScript-engine bepaalt dat. Het kan ervoor kiezen om de geheugenopruiming onmiddellijk uit te voeren of te wachten en de opschoning later uit te voeren wanneer er meer verwijderingen plaatsvinden. Dus technisch gezien is het huidige aantal elementen van een WeakMapniet bekend. De motor heeft het misschien schoongemaakt of niet of heeft het gedeeltelijk gedaan. Om die reden worden methoden die toegang hebben tot alle sleutels/waarden niet ondersteund.

Opmerking:-Het belangrijkste toepassingsgebied voor WeakMap is extra gegevensopslag. Zoals het cachen van een object totdat dat object wordt verzameld.


Antwoord 7, autoriteit 3%

WeapMap in javascript bevat geen sleutels of waarden, het manipuleert alleen de sleutelwaarde met een unieke iden definieert een eigenschap voor het sleutelobject.

omdat het de eigenschap definieert om key objectte gebruiken met de methode Object.definePropert(), mag de sleutel geen primitief type zijn.

en ook omdat WeapMap geen daadwerkelijke sleutelwaardeparen bevat, kunnen we de lengte-eigenschap van de zwakke kaart niet krijgen.

en ook gemanipuleerde waarde wordt terug toegewezen aan het sleutelobject, vuilnisophaler kan de sleutel gemakkelijk verzamelen als deze niet gebruikt wordt.

Voorbeeldcode voor implementatie.

if(typeof WeapMap != undefined){
return;
} 
(function(){
   var WeapMap = function(){
      this.__id = '__weakmap__';
   }
   weakmap.set = function(key,value){
       var pVal = key[this.__id];
        if(pVal && pVal[0] == key){
           pVal[1]=value;
       }else{
          Object.defineProperty(key, this.__id, {value:[key,value]});
          return this;
        }
   }
window.WeakMap = WeakMap;
})();

verwijzing naar implementatie

Other episodes