Set.prototype.forEach()
set.forEach(callbackFn, thisArg) The forEach() method executes the callback function once for each value in the Set, in insertion order. It returns undefined and does not produce a new collection — use it for side effects like logging, updating external state, or dispatching events.
One quirk of the callback signature: the first two arguments both receive the current value. This matches the Map.prototype.forEach signature (which provides value, key, map), making it easier to swap between the two without rewriting callbacks.
Syntax
set.forEach(callbackFn, thisArg)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
callbackFn | function | — | Function executed for each value. Receives (value, value, set). |
thisArg | any | undefined | Value to use as this inside the callback |
Return value
undefined.
Examples
Basic usage
const numbers = new Set([1, 2, 3]);
numbers.forEach((value, sameValue, set) => {
console.log(`Value: ${value}, Set size: ${set.size}`);
});
// Value: 1, Set size: 3
// Value: 2, Set size: 3
// Value: 3, Set size: 3
The third argument gives you access to the Set itself, which is useful when you need to check the collection size or membership inside the callback. The second argument is always a copy of the first — you can name it key if that makes your code clearer, but it does not give you a separate value the way Map.prototype.forEach does.
Using thisArg
const multiplier = {
factor: 10
};
const nums = new Set([1, 2, 3]);
nums.forEach(function(value) {
console.log(value * this.factor);
}, multiplier);
// 10
// 20
// 30
thisArg binds the callback’s this to the specified object. Note that arrow functions ignore thisArg because they capture this lexically from the enclosing scope. Use a regular function expression when you need the binding — otherwise this will not refer to the object you passed.
Processing unique values
const duplicates = [1, 2, 2, 3, 3, 3, 4, 4, 5];
const uniqueSet = new Set(duplicates);
const doubled = [];
uniqueSet.forEach(value => {
doubled.push(value * 2);
});
console.log(doubled);
// [2, 4, 6, 8, 10]
Building a result from Set contents
The previous example used an external array to collect results. This pattern is common when you need to transform Set data into another format — HTML strings, API payloads, or computed values — without modifying or altering the original Set in any way.
const tags = new Set(['javascript', 'css', 'html']);
const tagElements = [];
tags.forEach(tag => {
tagElements.push(`<span class="tag">${tag}</span>`);
});
console.log(tagElements.join(' '));
// <span class="tag">javascript</span> ...
Comparing forEach vs for…of
For most iteration work, for...of is more flexible than forEach because it supports break and continue. Use forEach when you prefer the callback style or need to pass a thisArg — the functional pattern can make side-effect code easier to trace.
const set = new Set([10, 20, 30]);
// forEach — no early exit
set.forEach(v => console.log(v));
// for...of — supports break
for (const v of set) {
if (v > 10) break;
console.log(v);
}
When forEach() is not the right choice
forEach() has no way to exit early. If you need to stop iteration when a condition is met, use a for...of loop with break instead. Similarly, forEach() returns undefined, so you cannot chain it — if you want a transformed result, use Array.prototype.map() or filter() after spreading the Set.
const set = new Set([1, 2, 3, 4, 5]);
// forEach: cannot break early
set.forEach(v => {
console.log(v);
// no way to stop at 3
});
// for...of: supports break
for (const v of set) {
if (v > 3) break;
console.log(v); // 1, 2, 3
}
Mutation during iteration
If you add values inside the callback, those values will also be visited during the current iteration if they have not been seen yet. Deleting values inside the callback removes them from the Set but does not affect already-visited entries. This behaviour is consistent with Map.prototype.forEach and for...of iteration.
When forEach() fits best
forEach() is a good choice when the goal is a side effect rather than a transformed result. Logging, dispatching actions, and collecting external data are all natural uses because the callback can stay focused on one job. If you need to build a new array or stop early, for...of or one of the array conversion methods is usually a better fit. That division keeps the API choice aligned with the shape of the work.