javascript
ecmascript-6
ecmascript-harmony
weakmap
Дмитрий Сорин
источник
источник
key
не могут быть собраны, потому что на него ссылаются вы.Ответы:
С той же страницы, раздел « Почему слабая карта? » :
[И поэтому у них тоже нет
size
собственности]- которые были бы «нормальными»
Map
s . Не упоминается в MDN, но в предложении гармонии , те такжеitems
,keys
иvalues
методы генератора и реализоватьIterator
интерфейс .источник
new Map().get(x)
что время поиска примерно такое же, как и при чтении свойства из простого объекта?WeakMap
все еще имеет массив (или другую коллекцию) записей, он просто сообщает сборщику мусора, что это слабые ссылки .Оба они ведут себя по-разному, когда объект, на который ссылаются их ключи / значения, удаляется. Возьмем приведенный ниже пример кода:
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}
и{y: 12}
больше. Сборщик мусора удаляет указатель ключа b из «WeakMap», а также удаляет его{y: 12}
из памяти. Но в случае «Карта» сборщик мусора не удаляет указатель с «Карты», а также не удаляет{x: 12}
из памяти.Описание: WeakMap позволяет сборщику мусора выполнять свою задачу, но не Map.
Ссылки: http://qnimate.com/difference-between-map-and-weakmap-in-javascript/
источник
map.entries().next().value // [{x:12}, 1]
WeakMap
может иметь только непримитивные ключи (без строк, чисел илиSymbol
s в качестве ключей, только массивы, объекты, другие карты и т. Д.).Map
но не вWeakMap
Возможно, следующее объяснение будет для кого-то более понятным.
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, это просто ссылки на другие объекты.
источник
forEach
,(key, val)
должно быть на самом деле(val, key)
Еще одно отличие (источник: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap ):
Также нельзя использовать строку, число или логическое значение в качестве
WeakMap
ключа. AMap
может использовать примитивные значения для ключей.w = new WeakMap; w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key m = new Map m.set('a', 'b'); // Works
источник
Из Javascript.info
Карта - если мы используем объект в качестве ключа в обычной карте, то пока существует карта, этот объект также существует. Он занимает память и не подлежит сборке мусора.
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]
Аналогично этому, если мы используем объект в качестве ключа в обычной карте, тогда, пока существует карта, этот объект также существует. Он занимает память и не подлежит сборке мусора
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 - Теперь, если мы используем объект в качестве ключа в нем, и нет других ссылок на этот объект - он будет автоматически удален из памяти (и с карты).
let john = { name: "John" }; let weakMap = new WeakMap(); weakMap.set(john, "..."); john = null; // overwrite the reference // john is removed from memory!
источник
WeapMap в javascript не содержит никаких ключей или значений, он просто манипулирует значением ключа, используя уникальный идентификатор, и определяет свойство для ключевого объекта.
поскольку он определяет свойство
key object
по методуObject.definePropert()
, ключ не должен быть примитивного типа .а также из-за того, что WeapMap фактически не содержит пар ключ-значение, мы не можем получить свойство length для 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; })();
ссылка на реализацию
источник
id
запрограммированный код, но он должен быть уникальным за счет использования чего-то Math.random и Date.now () и т. Д. И добавив этот динамический идентификатор, можно решить первую проблему. Не могли бы вы дать мне решение по последним двум пунктам.WeakMap
ключи должны быть объектами, а не примитивными значениями.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
Зачем????
Давайте посмотрим на пример ниже.
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()
let user = { name: "User" }; let weakMap = new WeakMap(); weakMap.set(user, "..."); user = null; // overwrite the reference // 'user' is removed from memory!
WeakMap
не поддерживает итерацию и методы keys () , values () , entries () , поэтому получить из него все ключи или значения невозможно.WeakMap имеет только следующие методы:
Это очевидно, как если бы объект потерял все другие ссылки (например, «пользователь» в приведенном выше коде), он должен быть автоматически собран в мусор. Но технически точно не указано, когда произойдет очистка.
Это решает движок JavaScript. Он может выбрать немедленную очистку памяти или подождать и выполнить очистку позже, когда произойдет еще несколько удалений. Итак, технически текущее количество элементов
WeakMap
неизвестно. Двигатель мог очистить его или нет, или сделал это частично. По этой причине методы, которые обращаются ко всем ключам и значениям, не поддерживаются.источник