Skip to the solution
HardDSA5 min read

How would you make a custom class iterable with for...of by implementing Symbol.iterator as a generator method?

936 views

The problem

Question presented to candidate: "You have a custom class β€” say, a Range representing start/end/step β€” and for (const n of myRange) currently throws. What exactly makes an object 'iterable' in JavaScript, and how would you implement that using a generator method specifically, rather than hand-writing the iterator protocol by hand?"

What a strong answer should cover:

  • An object is iterable if it has a method keyed by the well-known symbol Symbol.iterator that returns an iterator β€” an object with a next() method returning { value, done }. for...of, spread (...), destructuring, and Array.from all work by calling this method internally.
  • πŸ“Œ Verified, not assumed: a plain class with no Symbol.iterator genuinely threw a real TypeError ("is not iterable") the instant for...of was used on it β€” not a silent no-op.
  • πŸ“Œ Interview term: a generator method as Symbol.iterator β€” writing *[Symbol.iterator]() { ... } on a class lets the method itself BE the iterator factory: calling it returns a real generator object, which already correctly implements next()/done/return() β€” the entire manual iterator-protocol boilerplate (a hand-written next() method tracking state, PLUS a hand-written return() method for cleanup) collapses into a single function using yield.
  • πŸ“Œ Verified, not assumed β€” the real cleanup advantage: breaking out of a real for...of loop early genuinely triggered the generator method's own finally block automatically, with zero extra code β€” the identical cleanup behavior in a manually-written iterator object required a hand-written return() method, verified directly, to achieve the same result.
  • A precise answer names that this identical generator method genuinely works for spread, array destructuring, and Array.from too β€” since all of them consume the same Symbol.iterator method, not something special to for...of alone.

Clarifying questions expected:

  • "Does the underlying data need to be computed lazily (one value at a time, only as requested), or is it acceptable to already have the whole collection in memory?" β€” a generator's real, lazy, pull-based evaluation is a genuine advantage specifically for large or infinite sequences, not just a syntax preference.
  • "Does any consumer need to iterate the SAME instance multiple times concurrently?" β€” a generator-based Symbol.iterator method genuinely creates a fresh, independent generator on every call, so this works correctly by default, but is worth confirming.

Code / implementation expected: Yes β€” a real, running for...of/spread/destructuring/Array.from demonstration over a custom iterable class, plus a real proof that an early break genuinely triggers the generator's own cleanup code, is the concrete way to prove the mechanism rather than just describe it.

  • iterators
  • tricky
  • real-world

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

5 min read Β· 9 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

JavaScriptA real, runnable Range class made iterable via a Symbol.iterator generator method β€” for...of, spread, destructuring, Array.from, and early-exit cleanup

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 130 of 165 in JavaScript

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextHard

What is the Reflect API?

Continue