Capítulo 21 de 36

Chapter 21: Iterators and Generators

Core Idea

An object is iterable purely by implementing Symbol.iterator; for..of consumes that protocol to walk values (not keys), and the compiler's emitted code for it depends heavily on target — full native iterator support only kicks in at ES2015+.

Key Concepts

  • Iterable<T> interface: the type to use when a parameter should accept anything implementing Symbol.iterator — arrays, Map, Set, strings, typed arrays all qualify natively. A generic function like toArray<X>(xs: Iterable<X>): X[] accepts any of them uniformly.
  • for..of vs. for..in: for..of iterates values (via the object's Symbol.iterator); for..in iterates keys (as strings) and works on any object, not just iterables — it's an object-property-inspection tool, not a values-consumption tool. On an array, for..in yields index strings ("0", "1", ...) while for..of yields the actual elements. On a Set/Map, for..in only picks up enumerable own properties (e.g. a manually assigned extra property), while for..of yields the actual stored values via the iterator protocol.
  • Code generation depends on target:
    • ES5 and below: for..of is only legal on Array-typed values (a compile error otherwise, even for objects that do implement Symbol.iterator) — the compiler downlevels it to a plain indexed for loop, since ES5 has no native iterator protocol to lean on.
    • ES2015+: the compiler emits a native for..of loop directly, using the runtime's built-in iterator protocol — works for any iterable, not just arrays.

Code Examples

const pets = new Set(["Cat", "Dog"]);
for (const p of pets) console.log(p); // "Cat", "Dog" — values via Symbol.iterator
for (const p in pets) console.log(p); // only enumerable own properties, not the Set's contents
  • What it demonstrates: for..of walking a Set's actual stored values through its iterator, versus for..in's unrelated key-enumeration behavior on the same object.

Key Takeaways

  1. Reach for for..of to consume values from anything iterable; reserve for..in for genuinely inspecting an object's own enumerable property names.
  2. If a project must support pre-ES2015 runtimes, for..of is restricted to arrays — check target before relying on it for Map/Set/custom iterables.
  3. Type a "works with any iterable" function parameter as Iterable<T> rather than a specific concrete type like T[].

Connects To

  • Symbols (next chapter): Symbol.iterator itself, the protocol this whole chapter is built on.
  • Generic Object Types: Array<T>/Map<K,V>/Set<T> are all iterable generics.