WeakSet

A set of objects that doesn’t keep them in memory. Used for marking objects, e.g. ones already handled.

Returns
A new WeakSet object.
On this page

Example

#
JavaScript
const completed = new WeakSet()

const lesson1 = { title: 'Variables' }
const lesson2 = { title: 'Loops' }

completed.add(lesson1)

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

The third check is for a new object with the same content. The set compares objects by reference, so it doesn’t find it.

Definition and usage

#

WeakSet is a set similar to Set, but it stores objects, not strings or numbers: trying to add a string or a number throws a TypeError. The set holds its objects "weakly". Once nothing else in the program references an object, the engine can remove it from memory, and the object simply disappears from the set.

It has only three methods: add(), has(), and delete(). It has no size, clear(), forEach(), or any way to iterate over its elements, because its contents can change at any moment while the garbage collector is running. So all you can ask is whether a specific object is in the set.

A typical use is marking objects without changing them: remembering which DOM elements have already been handled, which objects you’ve visited while walking nested data, or which students have already received a reward. Once an object is no longer needed, its entry disappears along with it, with no risk of a memory leak.

Syntax

#
Syntax
new WeakSet()
new WeakSet(iterable)

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

Parameters

#
  • iterable

    optional

    An array or other iterable of objects the set is initially filled with.

More examples

#
Only objects, and no way to preview contents
JavaScript
const seen = new WeakSet()

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

seen.add({ id: 1 })
console.log(seen.size)
console.log(seen)
Console
TypeError
undefined
WeakSet {}
A reward granted only once
JavaScript
const rewarded = new WeakSet()

function award(student) {
  if (rewarded.has(student)) {
    return `${student.name} already has the badge`
  }
  rewarded.add(student)
  return `Badge awarded to ${student.name}`
}

const emma = { name: 'Emma' }

console.log(award(emma))
console.log(award(emma))
Console
Badge awarded to Emma
Emma already has the badge
Detecting cycles in data
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))
Console
false
true

JSON.stringify() throws an error for data with a cycle, and a function like this lets you check for one beforehand. The set only holds objects from the current path, so after a value’s children have been checked, it’s removed again.

Browser support

#

Widely available

Works in all modern browsers, phones included. You can use it without worry.

  • Chrome
  • Edge
  • Firefox
  • Safari

Good practices

#
  • Choose WeakSet when you only need the answer to "is this object marked". If you want to attach extra data to the object, use WeakMap.
  • If you need to know the number of elements or loop over them, choose a regular Set. WeakSet deliberately doesn’t allow that.
  • There’s no way to predict when an unused object will disappear from the set. Don’t base your program’s logic on the timing of garbage collection.

Related entries

#

Spotted a mistake or missing an example? Write to us.