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)); // false
Para 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)); // false
O 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)); // false
Referê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
.