WeakSet
This lesson explains WeakSet with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.
ES6+ WeakSet Overview
WeakSet is an ES6 collection that stores unique
objects using weak references. Unlike a regular
Set, a WeakSet does not prevent its
objects from being garbage collected when no other references to
them exist.
WeakSet is useful when you need to track object membership
temporarily without causing memory leaks. Common examples include
marking DOM nodes as processed, preventing duplicate event handler
attachment, and tagging objects for internal library logic.
| Feature | Description |
| Introduced In | ES6 (ECMAScript 2015) |
| Stores | Objects only |
| Reference Type | Weak references |
| Main Methods | add(), has(), delete() |
| Iterable | No — cannot loop or get size |
| Common Uses | Object tagging, DOM tracking, memory-safe membership |
Basic WeakSet Example
const visitedUsers =
new WeakSet();
const userA = { id: 1, name: "Alex" };
const userB = { id: 2, name: "Sam" };
visitedUsers.add(userA);
visitedUsers.add(userB);
console.log(visitedUsers.has(userA));
console.log(visitedUsers.has(userB));
visitedUsers.delete(userA);
console.log(visitedUsers.has(userA));
A WeakSet works like a Set for checking membership, but it only
accepts objects. Use add(), has(), and
delete() to manage tracked objects.
How WeakSet Works
When you add an object to a WeakSet, the collection holds a weak
reference to that object. If the object is removed from your
application and no strong references remain, JavaScript can garbage
collect it and automatically remove it from the WeakSet.
| Step | Description | Example Syntax |
| Create WeakSet | Initialize an empty collection. | const set = new WeakSet() |
| Add Object | Track an object by reference. | set.add(user) |
| Check Membership | See whether the object is tracked. | set.has(user) |
| Remove Object | Delete the object from the set. | set.delete(user) |
| Garbage Collection | Untracked objects may disappear automatically. | No manual cleanup required |
WeakSet vs Set
| Feature | WeakSet | Set |
| Value Types | Objects only. | Any value, including primitives. |
| References | Weak references. | Strong references. |
| Garbage Collection | Entries may be removed automatically. | Entries stay until deleted. |
| Iterable | No. | Yes. |
size | Not available. | Available. |
| Best For | Temporary object tagging. | General unique value storage. |
WeakSet Accepts Objects Only
const tags =
new WeakSet();
const product = {
id: 101,
name: "Laptop"
};
tags.add(product);
console.log(tags.has(product));
// This throws a TypeError
// tags.add("laptop");
// tags.add(101);
// tags.add(true);
WeakSet cannot store strings, numbers, booleans, or other
primitives. It only works with object references such as plain
objects, arrays, functions, and DOM nodes.
Track Processed DOM Nodes
const initializedElements =
new WeakSet();
function setupTooltip(element) {
if (initializedElements.has(element)) {
return;
}
element.addEventListener("mouseenter", () => {
console.log("Show tooltip");
});
initializedElements.add(element);
}
const button =
document.querySelector("#helpButton");
setupTooltip(button);
setupTooltip(button);
WeakSet is ideal for marking DOM elements that already received
setup logic. If the element is removed from the page and garbage
collected, the WeakSet entry disappears automatically.
Prevent Duplicate Processing
const processedRequests =
new WeakSet();
function handleRequest(request) {
if (processedRequests.has(request)) {
console.log("Already handled.");
return;
}
console.log("Processing request...");
processedRequests.add(request);
}
const requestA = { url: "/api/users" };
const requestB = { url: "/api/orders" };
handleRequest(requestA);
handleRequest(requestA);
handleRequest(requestB);
Use WeakSet when you need to remember which object instances were
already handled without keeping those objects alive longer than
necessary.
Tag Objects Internally
const validatedForms =
new WeakSet();
function validateForm(formObject) {
if (validatedForms.has(formObject)) {
return true;
}
const isValid =
formObject.email.includes("@");
if (isValid) {
validatedForms.add(formObject);
}
return isValid;
}
const signupForm = {
email: "alex@example.com"
};
console.log(validateForm(signupForm));
console.log(validatedForms.has(signupForm));
Libraries and modules can use WeakSet to attach internal state to
objects without modifying the objects themselves or exposing extra
properties on them.
Weak References and Garbage Collection
const cache =
new WeakSet();
function trackTempObject() {
const temp = { id: Date.now() };
cache.add(temp);
return temp;
}
let item = trackTempObject();
console.log(cache.has(item));
item = null;
// Later, when temp has no other references,
// it can be garbage collected and removed
// from the WeakSet automatically
Because WeakSet does not strongly hold objects, it helps avoid
memory leaks in long-running applications where temporary object
tracking is needed.
WeakSet Methods
| Method | Description | Example |
add(value) | Adds an object to the WeakSet. | set.add(user) |
has(value) | Returns true if the object exists. | set.has(user) |
delete(value) | Removes an object from the WeakSet. | set.delete(user) |
WeakSet Limitations
- Cannot store primitive values such as strings or numbers.
- Has no
size property. - Cannot iterate with
for...of. - No
forEach(), keys(), or values() methods. - Cannot convert directly to an array.
- Membership checks only work if you still hold the object reference.
Common WeakSet Use Cases
- Marking DOM nodes that already have event listeners attached.
- Preventing duplicate initialization of components or plugins.
- Tracking temporary object instances during processing.
- Tagging validated, cached, or authenticated object instances.
- Internal library bookkeeping without modifying user objects.
- Memory-safe membership tracking in long-lived applications.
WeakSet Best Practices
- Use WeakSet only when object membership tracking is enough.
- Prefer WeakSet over Set when garbage collection matters.
- Keep a strong reference to an object if you need to check it later.
- Use regular Set when you need iteration, size, or primitives.
- Do not expect to list all items stored in a WeakSet.
- Combine WeakSet with clear object lifecycle management.
- Document why weak membership tracking is needed in your code.
Common WeakSet Mistakes
- Trying to store strings, numbers, or booleans in a WeakSet.
- Expecting to loop through WeakSet contents.
- Using WeakSet when a Map or Set with iteration is required.
- Assuming
has() works after losing all object references. - Using WeakSet for general-purpose unique value storage.
- Expecting a
size property to count stored objects. - Choosing WeakSet without understanding garbage collection behavior.
WeakSet vs WeakMap
| Feature | WeakSet | WeakMap |
| Stores | Objects only. | Key-value pairs with object keys. |
| Main Question | "Is this object a member?" | "What value belongs to this object?" |
| Methods | add(), has(), delete() | set(), get(), has(), delete() |
| Best For | Tagging or membership checks. | Private metadata attached to objects. |
Key Takeaways
- WeakSet is an ES6 collection for tracking unique object references.
- It uses weak references, so objects can be garbage collected naturally.
- Use
add(), has(), and delete() to manage membership. - WeakSet cannot store primitives and is not iterable.
- Choose WeakSet for memory-safe object tagging, not general data storage.
Pro Tip
If you only need to know whether an object was seen before, use
WeakSet. If you need to store extra data on that object, use
WeakMap instead.