Iterator vs Generator — What’s the Difference?
Bharathvaj

Bharathvaj @bharathvaj_ganesan

About: I'm a software engineer with 7+ years of experience, passionate about building purposeful products with strong technical depth. Currently leading AI initiatives at Chargebee.

Location:
Chennai
Joined:
Sep 20, 2020

Iterator vs Generator — What’s the Difference?

Publish Date: May 1
3 0

Iterators and generators are closely related and often used together, they are not the same. Let’s break it down clearly.

🔁 Iterator

An iterator is an object that defines a sequence and potentially a return value upon completion. It must implement a next() method that returns an object with value and done properties.

Use iterators when:

  • You want fine-grained control over iteration.
  • You are implementing custom data structures (e.g., trees, graphs) that need to conform to the iterable protocol.
  • You want to manually manage the state of iteration.

Example

function createIterator(arr) {
  let index = 0;
  return {
    next: function () {
      if (index < arr.length) {
        return { value: arr[index++], done: false };
      } else {
        return { done: true };
      }
    }
  };
}

const it = createIterator([10, 20, 30]);
console.log(it.next()); // { value: 10, done: false }
console.log(it.next()); // { value: 20, done: false }
console.log(it.next()); // { value: 30, done: false }
console.log(it.next()); // { done: true }
Enter fullscreen mode Exit fullscreen mode

⚙️ Generator

A generator is a special function using function* syntax that can pause and resume execution using the yield keyword.

Use generators when:

  • You need lazy evaluation or infinite sequences.
  • You want to create iterators more simply.
  • You need to pause and resume logic (like co-routines).
  • You're working with asynchronous flows (using async generators with for await).

Example

function* numberGenerator() {
  yield 10;
  yield 20;
  yield 30;
}

const gen = numberGenerator();
console.log(gen.next()); // { value: 10, done: false }
console.log(gen.next()); // { value: 20, done: false }
console.log(gen.next()); // { value: 30, done: false }
console.log(gen.next()); // { value: undefined, done: true }
Enter fullscreen mode Exit fullscreen mode

🆚 Key Differences

Feature Iterator Generator
Syntax Manual object with next() Uses function* and yield
Code Complexity More verbose Concise and readable
State Management Manual Automatically managed
Reusability Custom setup needed Can be reused easily
Use in Loops Harder, manual loop Works with for...of out of the box
Lazy Evaluation Yes, but manually Yes, naturally supported
Pause/Resume logic No Yes, with yield
Async Support No (without Promises) Yes, via async function*

Examples

🐍 Python Example

Iterator

class MyIterator:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= self.limit:
            raise StopIteration
        val = self.current
        self.current += 1
        return val

it = MyIterator(3)
for val in it:
    print(val)  # 0 1 2
Enter fullscreen mode Exit fullscreen mode

Generator

def my_generator(limit):
    for i in range(limit):
        yield i

for val in my_generator(3):
    print(val)  # 0 1 2
Enter fullscreen mode Exit fullscreen mode

🌐 JavaScript Example

Iterator (Manual)

const myIterator = {
  current: 0,
  limit: 3,
  [Symbol.iterator]() {
    return {
      current: this.current,
      limit: this.limit,
      next() {
        if (this.current < this.limit) {
          return { value: this.current++, done: false };
        }
        return { done: true };
      }
    };
  }
};

for (const item of myIterator) {
  console.log(item);
}
Enter fullscreen mode Exit fullscreen mode

Generator

function* myGenerator(limit) {
  for (let i = 0; i < limit; i++) {
    yield i;
  }
}

for (const val of myGenerator(3)) {
  console.log(val); // 0 1 2
}
Enter fullscreen mode Exit fullscreen mode

You can also have async generator but you need to await the iterator.

async function* myGenerator(limit) {
  for (let i = 0; i < limit; i++) {
    yield i;
  }
}

for await (const val of myGenerator(3)) {
  console.log(val); // 0 1 2
}
Enter fullscreen mode Exit fullscreen mode

✅ Summary

  • Use generators when you want a simpler, more powerful way to create iterators or need to pause/resume execution. When performance optimization is needed.
  • Use iterators when you want custom control over how iteration works or need to implement the iterator protocol manually.

Comments 0 total

    Add comment