В чем разница между ES6 Map и WeakMap?


просмотр этой и этой страницы MDN похоже, что единственное различие между картами и слабыми картами-это отсутствие свойства "размер" для слабых карт. Но правда ли это? Какая между ними разница?

5 74

5 ответов:

С та же страница, раздел"почему слабый карте?":

опытный программист JavaScript заметит, что этот API может быть реализован в JavaScript с двумя массивами (один для ключей, один для значения) совместно используются 4 метода API. Такая реализация имела бы два главных неудобства. Первый-это поиск O(n) (n-это количество ключей на карте). Второй-это проблема утечки памяти. С вручную написанными картами,массив ключей будет содержать ссылки на ключевые объекты, предотвращающие их сбор мусора. На родном языке WeakMaps, ссылки на ключевые объекты проводятся "слабо", что означает чтобы они не мешали сборке мусора в случае, если бы не было другая ссылка на объект.

из-за слабых ссылок ключи WeakMap не перечисляются (т. е. нет никакого метода, дающего вам список ключей). Если бы они были, список будет зависеть от состояния сборки мусора, вводя недетерминизм.

[и поэтому у них нет size свойства]

если вы хотите получить список ключей, вы должны поддерживать его самостоятельно. Существует также ECMAScript предложение стремясь ввести простые наборы и карты, которые не будут использовать слабые ссылки и были бы перечислимы.

‐ что будет будь "нормальные" Maps. Не упоминается в MDN, но в предложение о гармонии, и у items,keys и values методы генератора и реализовать Iterator интерфейс.

они оба ведут себя по-разному, когда объект, на который ссылается ключей/значений удаляется. Давайте возьмем приведенный ниже пример кода:

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

выше IIFE выполняется нет никакого способа, мы можем ссылаться {x: 12} и

может быть, следующее объяснение будет более понятным для кого-то.

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

Как видите, после удаления k1 ключ из памяти мы все еще можем получить доступ к его внутренней карте. В то же время удаление k2 ключ WeakMap удаляет его из wm а также по ссылке.

вот почему WeakMap не имеет перечислимых методов, таких как forEach, потому что нет такой вещи, как список ключей WeakMap, они просто ссылки на другие объекты.

еще одно различие:

ключи WeakMaps относятся только к типу Object. Примитивные типы данных как ключи не допускаются (например, символ не может быть ключом WeakMap).

также нельзя использовать строку, число или логическое значение в качестве WeakMap ключ. А Mapможете использовать примитивные значения для ключей.

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

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

WeapMap в javascript не содержит никаких ключей или значений, он просто манипулирует значением ключа с помощью уникальный идентификатор и определить свойство ключевого объекта.

потому что он определяет свойство key методом Object.definePropert(), ключ не должен быть примитивного типа.

а также потому, что WeapMap не содержит фактически пары ключевых значений, мы не можем получить свойство длины weakmap.

и также манипулированное значение назначено назад к ключу, сборщику отброса легко может соберите ключ, если он не используется.

пример кода для реализации.

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

ссылка реализация