WeakMap em JavaScript
WeakMap representa uma evolução da coleção Map. A característica distintiva do WeakMap é que todos os seus elementos devem ser objetos, e os mesmos requisitos se aplicam às chaves.
Criação de um WeakMap:
// WeakMap vazio
const weakMap1 = new WeakMap();
// WeakMap com dados inicializados
let key1 = { key: 1 };
let key2 = { key: 2 };
let value1 = { name: "Tom" };
let value2 = { name: "Sam" };
const weakMap2 = new WeakMap([
[key1, value1],
[key2, value2],
]);É importante notar que um objeto WeakMap não suporta iteração.
Para adicionar um par chave-valor ao WeakMap, utiliza-se o método set():
let key1 = { key: 1 };
let key2 = { key: 2 };
let value1 = { name: "Tom" };
let value2 = { name: "Sam" };
const weakMap2 = new WeakMap([[key1, value1]]);
weakMap2.set(key2, value2);
weakMap2.set(key1, { name: "Kate" });
console.log(weakMap2.get(key1)); // {name: "Kate"}
console.log(weakMap2.get(key2)); // {name: "Sam"}Para recuperar objetos por chave no WeakMap, utiliza-se o método get():
let key1 = { key: 1 };
let key2 = { key: 2 };
let value1 = { name: "Tom" };
let value2 = { name: "Sam" };
const weakMap2 = new WeakMap([
[key1, value1],
[key2, value2],
]);
console.log(weakMap2.get(key1)); // {name: "Tom"}Para verificar a presença de um elemento por uma chave específica, usa-se o método has(), que retorna true se o elemento estiver presente:
let key1 = { key: 1 },
key2 = { key: 2 };
let value1 = { name: "Tom" },
value2 = { name: "Sam" };
const weakMap2 = new WeakMap([[key1, value1]]);
console.log(weakMap2.has(key1)); // true
console.log(weakMap2.has(key2)); // falsePara remover um elemento, usa-se o método delete(), passando a chave do elemento a ser removido:
let key1 = { key: 1 },
key2 = { key: 2 };
let value1 = { name: "Tom" },
value2 = { name: "Sam" };
const weakMap2 = new WeakMap([
[key1, value1],
[key2, value2],
]);
console.log(weakMap2.has(key1)); // true
weakMap2.delete(key1);
console.log(weakMap2.has(key1)); // falseO método clear() remove todos os elementos do WeakMap:
let key1 = { key: 1 },
key2 = { key: 2 };
let value1 = { name: "Tom" },
value2 = { name: "Sam" };
const weakMap2 = new WeakMap([
[key1, value1],
[key2, value2],
]);
console.log(weakMap2.has(key1)); // true
console.log(weakMap2.has(key2)); // true
weakMap2.clear();
console.log(weakMap2.has(key1)); // false
console.log(weakMap2.has(key2)); // falseReferências Fracas
Objetos são passados para WeakMap por referência. Uma característica distintiva do WeakMap é que quando um objeto deixa de existir por diversas razões, ele é automaticamente removido do WeakMap. Vamos considerar o exemplo a seguir:
let jsCode = { code: "js" },
tsCode = { code: "ts" };
let js = { lang: "JavaScript" },
ts = { lang: "TypeScript" };
const weakMap = new WeakMap([
[jsCode, js],
[tsCode, ts],
]);
jsCode = null;
console.log(weakMap);
console.log("Alguma operação");
const timerId = setTimeout(function () {
console.log(weakMap);
clearTimeout(timerId);
}, 30000);Inicialmente, o objeto WeakMap armazena referências a dois elementos com chaves jsCode e tsCode. Depois, a variável jsCode é configurada como null.
jsCode = null;Isso levará à remoção do valor inicial desta variável pelo coletor de lixo do JavaScript após algum tempo.
Enquanto isso, se usarmos Map no lugar de WeakMap:
let jsCode = { code: "js" },
tsCode = { code: "ts" };
let js = { lang: "JavaScript" },
ts = { lang: "TypeScript" };
const map = new Map([
[jsCode, js],
[tsCode, ts],
]);
jsCode = null;
console.log(map); // Map(2) {{code: "js"} => {lang: "JavaScript"}, {code: "ts"} => {lang: "TypeScript"} }
console.log("Alguma operação");
const timerId = setTimeout(function () {
console.log(map); // Map(2) {{code: "js"} => {lang: "JavaScript"}, {code: "ts"} => {lang: "TypeScript"} }
clearTimeout(timerId);
}, 30000);Mesmo após algum tempo, o objeto no Map ainda estará presente, mesmo que o valor original para o qual foi configurado seja null.