WeakSet

Zbiór obiektów, który nie zatrzymuje ich w pamięci. Służy do oznaczania obiektów, np. już obsłużonych.

Zwraca
Nowy obiekt WeakSet.
Na tej stronie

Przykład

#
JavaScript
const completed = new WeakSet()

const lesson1 = { title: 'Zmienne' }
const lesson2 = { title: 'Pętle' }

completed.add(lesson1)

console.log(completed.has(lesson1))
console.log(completed.has(lesson2))
console.log(completed.has({ title: 'Zmienne' }))
Konsola
true
false
false

Trzecie sprawdzenie dotyczy nowego obiektu o tej samej treści. Zbiór porównuje obiekty przez referencję, więc go nie znajduje.

Definicja i zastosowanie

#

WeakSet to zbiór podobny do Set, ale przechowuje obiekty, a nie napisy czy liczby: próba dodania napisu albo liczby kończy się błędem TypeError. Zbiór trzyma obiekty „słabo”. Gdy do obiektu nie prowadzi już żadne inne odwołanie w programie, silnik może usunąć go z pamięci, a obiekt po prostu zniknie ze zbioru.

Ma tylko trzy metody: add(), has() i delete(). Nie ma size, clear(), forEach() ani sposobu na przejście po elementach, bo zawartość może się zmienić w każdej chwili, gdy działa odśmiecanie pamięci (garbage collector). Możesz więc zapytać tylko o to, czy konkretny obiekt jest w zbiorze.

Typowe zastosowanie to oznaczanie obiektów bez ich zmieniania: zapamiętanie, które elementy DOM zostały już obsłużone, które obiekty odwiedziłeś przy przechodzeniu po zagnieżdżonych danych albo którzy uczniowie dostali już nagrodę. Gdy obiekt przestanie być potrzebny, jego wpis zniknie razem z nim, bez ryzyka wycieku pamięci.

Składnia

#
Składnia
new WeakSet()
new WeakSet(iterable)

weakSet.add(object)
weakSet.has(object)
weakSet.delete(object)

Parametry

#
  • iterable

    opcjonalny

    Tablica lub inny obiekt iterowalny z obiektami, którymi zbiór zostanie wypełniony na start.

Więcej przykładów

#
Tylko obiekty i brak podglądu zawartości
JavaScript
const seen = new WeakSet()

try {
  seen.add('Ania')
} catch (error) {
  console.log(error.name)
}

seen.add({ id: 1 })
console.log(seen.size)
console.log(seen)
Konsola
TypeError
undefined
WeakSet {}
Nagroda przyznawana tylko raz
JavaScript
const rewarded = new WeakSet()

function award(student) {
  if (rewarded.has(student)) {
    return `${student.name} ma już odznakę`
  }
  rewarded.add(student)
  return `Odznaka dla ${student.name}`
}

const ania = { name: 'Ania' }

console.log(award(ania))
console.log(award(ania))
Konsola
Odznaka dla Ania
Ania ma już odznakę
Wykrywanie cykli w danych
JavaScript
function hasCycle(value, path = new WeakSet()) {
  if (typeof value !== 'object' || value === null) return false
  if (path.has(value)) return true
  path.add(value)
  const found = Object.values(value).some((child) => hasCycle(child, path))
  path.delete(value)
  return found
}

const course = { title: 'JS', modules: [] }
console.log(hasCycle(course))

course.modules.push({ parent: course })
console.log(hasCycle(course))
Konsola
false
true

JSON.stringify() rzuca błąd dla danych z cyklem, a taka funkcja pozwala sprawdzić to wcześniej. Zbiór trzyma tylko obiekty z bieżącej ścieżki, dlatego po sprawdzeniu dzieci obiekt jest z niego usuwany.

Obsługa przeglądarek

#

Szeroko dostępne

Działa we wszystkich nowoczesnych przeglądarkach, także na telefonach. Możesz używać bez obaw.

  • Chrome
  • Edge
  • Firefox
  • Safari

Dobre praktyki

#
  • Wybierz WeakSet, gdy potrzebujesz tylko odpowiedzi „czy ten obiekt jest oznaczony”. Jeśli do obiektu chcesz przypiąć dodatkowe dane, użyj WeakMap.
  • Jeśli musisz znać liczbę elementów albo przejść po nich pętlą, wybierz zwykły Set. WeakSet celowo na to nie pozwala.
  • Nie da się przewidzieć, kiedy nieużywany obiekt zniknie ze zbioru. Nie opieraj logiki programu na momencie sprzątania pamięci.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.