JavaScript Generators, Symbols, Iterables, and Iterators
Advanced JavaScript features for managing iteration and data flow
JavaScript Generators, Symbols, Iterables, and Iterators
1. Symbols
-
Definition: A new primitive type introduced in ES6 that creates unique, immutable values.
const s1 = Symbol("id"); const s2 = Symbol("id"); console.log(s1 === s2); // false
-
Symbols are often used as “hidden keys” for object properties to avoid collisions.
Well-Known Symbols
JavaScript defines several built-in symbols with special purposes:
Symbol.iterator
: Marks an object as iterable.Symbol.toStringTag
: Customizes the result ofObject.prototype.toString
.Symbol.hasInstance
: Controls behavior ofinstanceof
.
2. Iterables
- Definition:
An object is iterable if it implements a method at key
Symbol.iterator
. - This method must return an iterator.
-
Iterables work with:
for...of
loops- Spread syntax (
...
) Array.from
-
Example:
const arr = [1, 2, 3]; console.log(typeof arr[Symbol.iterator]); // "function" for (const n of arr) console.log(n); // 1, 2, 3
3. Iterators
-
Definition: An iterator is an object with a
next()
method that returns:{ value: <any>, done: <boolean> }
-
Example:
const arr = [10, 20]; const it = arr[Symbol.iterator](); console.log(it.next()); // { value: 10, done: false } console.log(it.next()); // { value: 20, done: false } console.log(it.next()); // { value: undefined, done: true }
4. Iterable ↔ Iterator Relationship
- Iterable: An object that can produce an iterator (
obj[Symbol.iterator]
). - Iterator: The actual object that retrieves values sequentially via
next()
.
Analogy:
- Iterable → “You can loop over me; call my
Symbol.iterator
.” - Iterator → “I’ll hand out values one by one with
next()
.”
5. Custom Iterable Example
const myIterable = {
from: 1,
to: 3,
[Symbol.iterator]() {
let current = this.from;
let last = this.to;
return {
next() {
if (current <= last) {
return { value: current++, done: false };
} else {
return { done: true };
}
},
};
},
};
for (const num of myIterable) {
console.log(num); // 1, 2, 3
}
myIterable
is an iterable because it implements[Symbol.iterator]
.- The returned object is an iterator because it has
next()
.
6. Generators
- Definition: A special type of function that simplifies creation of iterables and iterators.
- Declared with
function*
and uses theyield
keyword. - Calling a generator returns an iterator that is also iterable.
-
Example:
function* genNumbers() { yield 1; yield 2; yield 3; } const it = genNumbers(); console.log(it.next()); // { value: 1, done: false } console.log(it.next()); // { value: 2, done: false } console.log(it.next()); // { value: 3, done: false } console.log(it.next()); // { value: undefined, done: true } for (const n of genNumbers()) { console.log(n); // 1, 2, 3 }
- Key property: Generators can pause at
yield
and resume execution later, producing values lazily.
7. Summary
- Symbol: A primitive for unique values. Includes well-known symbols like
Symbol.iterator
. - Iterable: Any object implementing
[Symbol.iterator]
, usable infor...of
, spread, etc. - Iterator: An object with
next()
that produces{ value, done }
. - Generator: A special function (
function*
) that produces iterators and iterables, supporting lazy evaluation viayield
.