WeakSet em JavaScript
O objeto WeakSet
é bastante semelhante a um conjunto comum. Ele também pode armazenar apenas valores únicos, mas cada um de seus elementos deve ser um objeto.
Para criar um objeto WeakSet
, usa-se seu construtor, que pode receber valores iniciais:
// WeakSet vazio
const weakSet1 = new WeakSet();
// Inicialização com valores iniciais
const weakSet2 = new WeakSet([
{ name: "Tom", age: 37 },
{ name: "Alice", age: 34 },
]);
Assim como com o objeto Set
, um array é passado para o construtor na inicialização, mas este array deve conter exclusivamente objetos, não valores escalares como números ou strings.
Para adicionar dados ao WeakSet
, utiliza-se o método add()
:
const weakSet = new WeakSet();
weakSet.add({ lang: "JavaScript" });
weakSet.add({ lang: "TypeScript" });
// weakSet.add(34); // Isso não é permitido - 34 é um número, não um objeto
console.log(weakSet); // WeakSet {{lang: "JavaScript"}, {lang: "TypeScript"} }
É possível adicionar apenas objetos, e não valores escalares como números ou strings.
Para remover um elemento, usa-se o método delete()
, no qual se passa a referência ao objeto a ser removido:
const weakSet = new WeakSet();
const js = { lang: "JavaScript" };
const ts = { lang: "TypeScript" };
weakSet.add(js);
weakSet.add(ts);
weakSet.delete(js);
console.log(weakSet); // {{lang: "TypeScript"} }
Para verificar a presença de um objeto no WeakSet
, pode-se utilizar o método has()
, que retorna verdadeiro se o objeto estiver presente:
const js = { lang: "JavaScript" };
const ts = { lang: "TypeScript" };
const java = { lang: "Java" };
const weakSet = new WeakSet([js, ts]);
console.log(weakSet.has(ts)); // true
console.log(weakSet.has(java)); // false
Iteração sobre WeakSet
É importante notar que o WeakSet
não suporta iteração, seja pelo método forEach
, que o WeakSet
não possui, seja pelo loop for
. Por exemplo, se tentarmos iterar um WeakSet
com um loop for
..of
:
const weakSet = new WeakSet([{ lang: "JavaScript" }, { lang: "TypeScript" }, { lang: "Java" }]);
for (item of weakSet) {
console.log(item);
}
Isso resultará em um erro:
Uncaught TypeError: weakSet is not iterable
Referências Fracas
Os objetos são passados para o WeakSet
por referência. Uma característica distintiva do WeakSet
é que, quando um objeto deixa de existir por qualquer motivo, ele é automaticamente removido do WeakSet
. Veja o exemplo a seguir:
let js = { lang: "JavaScript" };
let ts = { lang: "TypeScript" };
const weakSet = new WeakSet([js, ts]);
js = null;
console.log(weakSet); // {{lang: "JavaScript"}, {lang: "TypeScript"}}
console.log("Algum trabalho");
const timerId = setTimeout(function () {
console.log(weakSet); // {{lang: "TypeScript"}}
clearTimeout(timerId);
}, 20000);
Neste caso, o objeto WeakSet
inicialmente armazena referências a dois objetos: js
e ts
. Depois, o valor da variável js
é definido como null
. Isso faz com que, após algum tempo, o valor inicial dessa variável seja removido pelo coletor de lixo do JavaScript, liberando memória.
Para comparação, veja o que acontece com um Set
:
let js = { lang: "JavaScript" };
let ts = { lang: "TypeScript" };
const set = new Set([js, ts]);
js = null;
console.log(set); // Set(2) {{lang: "JavaScript"}, {lang: "TypeScript"}}
console.log("Algum trabalho");
const timerId = setTimeout(function () {
console.log(set); // Set(2) {{lang: "JavaScript"}, {lang: "TypeScript"}}
clearTimeout(timerId);
}, 20000);
Com o Set
, mesmo após algum tempo, o objeto para o qual o valor foi definido como null
ainda está presente no Set
.