WeakSet
Obiectul WeakSet este în multe privințe similar cu un set obișnuit. El poate stoca doar valori unice și fiecare element al său trebuie să reprezinte un obiect.
Pentru a crea un obiect WeakSet, se folosește constructorul său, în care pot fi furnizate valorile inițiale:
// WeakSet gol
const weakSet1 = new WeakSet();
// Inițializare cu valori inițiale
const weakSet2 = new WeakSet([{name:"Tom", age: 37}, {name:"Alice", age: 34}]);
Pentru inițializare, la fel ca în cazul obiectului Set, în constructor se furnizează un array, dar acest array conține în mod specific obiecte, nu valori scalare precum numere sau șiruri de caractere.
Pentru adăugarea datelor într-un WeakSet, se folosește metoda add():
const weakSet = new WeakSet();
weakSet.add({lang: "JavaScript"});
weakSet.add({lang: "TypeScript"});
// weakSet.add(34); // nu se poate - 34 este un număr, nu un obiect
console.log(weakSet); // {{lang: "JavaScript"}, {lang: "TypeScript"}}
De asemenea, trebuie menționat că putem adăuga doar obiecte, nu valori scalare precum numere sau șiruri de caractere.
Pentru ștergere, se folosește metoda delete(), la care se furnizează referința către obiectul de șters:
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"}}
Dacă trebuie să verificați dacă un obiect există într-un WeakSet, puteți utiliza metoda has(), care returnează true în cazul în care obiectul este prezent:
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
Iterarea prin WeakSet
Trebuie menționat că WeakSet nu susține iterarea nici prin intermediul metodei ForEach, pe care WeakSet nu o are, nici prin intermediul unui ciclu for. De exemplu, dacă încercăm să iterăm prin WeakSet folosind un ciclu for..of:
const weakSet = new WeakSet([
{lang: "JavaScript"},
{lang: "TypeScript"},
{lang: "Java"}
]);
for(item of weakSet){
console.log(item);
}
Vom primi o eroare:
Uncaught TypeError: weakSet nu este iterabil
Referințe slabe
Obiectele sunt adăugate într-un WeakSet prin referință. O caracteristică distinctivă a WeakSet este că atunci când un obiect încetează să mai existe din diverse motive, el este eliminat din WeakSet. Astfel, să luăm în considerare următorul exemplu:
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("Anumită muncă");
const timerId = setTimeout(function(){
console.log(weakSet); // {{lang: "TypeScript"}}
clearTimeout(timerId);
}, 20000);
În acest caz, mai întâi obiectul WeakSet stochează referințe către două obiecte: js și ts. Apoi, setăm valoarea variabilei js la null.
Acest lucru va duce la faptul că, după un anumit timp, valoarea inițială a acestei variabile va fi eliminată de colectorul de gunoi JavaScript.
js = null;
În cazul în care imediat după aceasta verificăm conținutul weakSet, vom vedea că obiectul js este încă prezent în el. Cu toate acestea, după un timp, referința va fi eliminată din weakSet. Pentru a simula trecerea timpului, aici se utilizează funcția setTimeout, care afișează conținutul weakSet la 9000 de milisecunde (perioada de timp specifică după care colectorul de gunoi va șterge valoarea poate diferi).
Acum, să comparăm cu ceea ce se întâmplă dacă folosim Set în loc de WeakSet:
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("Anumită muncă");
const timerId = setTimeout(function(){
console.log(set); // Set(2){{lang: "JavaScript"}, {lang: "TypeScript"}}
clearTimeout(timerId);
}, 20000);
În cazul unui Set, chiar și după un anumit timp, vom observa că obiectul pentru care a fost setată valoarea null este încă prezent în obiectul Set.