DEV Community

Cover image for Iterators in JavaScript Explained with Coffeeshops
Arpy Vanyan
Arpy Vanyan

Posted on Edited on

Iterators in JavaScript Explained with Coffeeshops

An Iterator is an Iterable of Itself

Wait… What?! 🤯

Yeah, I know—it sounds like a weird riddle from a programming wizard. But trust me, once you get it, you’ll never forget it.

JavaScript Iterators are often misunderstood, but the truth is:

"An Iterator is just an Iterable of itself."

💡 Let’s break down this concept with a fun analogy, some visual aids, and real-life relatable examples. If you’ve ever waited in line at a coffee shop, you already know how iterators work. ☕🔄


🎯 TL;DR

  • Iterables have a Symbol.iterator() method.
  • Iterators have a next() method that returns { value, done }.
  • If an iterator returns itself from Symbol.iterator, it becomes an iterable of itself.
  • Coffee queues act like iterables. ☕

Imagine a Coffee Queue

Picture this: you walk into your favorite coffee shop and see a queue of people waiting to order.

This queue of customers is like a JavaScript iterable—a collection of people you can go through one by one.

And guess what? The person serving the line (the barista) is like the iterator.

  • The queue = Iterable (the collection)
  • 👩‍🍳 The barista = Iterator (the one going through the collection)

🧠 Here’s the key insight:

The barista (iterator) is also part of the queue (iterable).


🤯 Wait… How?

In JavaScript:

  • An iterator is an object that knows how to access items one-by-one.
  • An iterable is an object that has a special method (Symbol.iterator) that returns an iterator.

💡 The twist:

If an iterator returns itself when Symbol.iterator is called, it’s both an iterator and an iterable. 🤯


🎯 Code Time! Let's See It in Action

Here's a simple custom iterator in JavaScript that iterates over coffee orders:

const coffeeOrders = {
  orders: ["Latte", "Espresso", "Cappuccino"],
  index: 0,

  // Iterator next() method
  next() {
    if (this.index < this.orders.length) {
      return { value: this.orders[this.index++], done: false };
    }
    return { value: undefined, done: true };
  },

  // Make the object an iterable of itself
  [Symbol.iterator]() {
    return this;
  }
};

// Iterating through coffee orders
for (const order of coffeeOrders) {
  console.log(`☕ Order: ${order}`);
}
Enter fullscreen mode Exit fullscreen mode

🧠 What's Happening Here?

  1. next() Method: The barista (iterator) goes through each coffee order one by one.
  2. Symbol.iterator() Method: Returns this, meaning the iterator is also the iterable.

📌 Output:

☕ Order: Latte
☕ Order: Espresso
☕ Order: Cappuccino

💡 See what we did there?
By returning this inside Symbol.iterator(), we made the same object act as both the iterator and the iterable.


🖼️ Visualizing the Concept

Imagine this coffee queue visually:

+---------------------+
|  ☕ Latte            |
+---------------------+
|  ☕ Espresso         |
+---------------------+
|  ☕ Cappuccino       |
+---------------------+
|  👩‍🍳 Barista (Iterator)|
+---------------------+
Enter fullscreen mode Exit fullscreen mode

The Barista (iterator) moves through each order.
But... the Barista is also in the queue.

The barista is both:

  • Serving the orders (iterator)
  • Part of the queue (iterable)

🧠 So... Why Does This Matter?

Understanding that "An Iterator Is an Iterable of Itself" helps when:

  • Creating custom iterators like the coffeeOrders example.
  • Working with generator functions (which return themselves as iterators).
  • Debugging confusing iterator-related bugs.

🔍 Built-in Iterators That Follow This Rule

JavaScript already does this with arrays, sets, maps, and strings.

Check this out:

const drinks = ["Tea", "Coffee", "Juice"];

// The array is both iterable and has an iterator
console.log(drinks[Symbol.iterator]() === drinks[Symbol.iterator]()); // false (new iterator each time)

// But calling next() works just like with our custom iterator:
const drinkIterator = drinks[Symbol.iterator]();
console.log(drinkIterator.next()); // { value: 'Tea', done: false }
}
Enter fullscreen mode Exit fullscreen mode

Arrays don't return themselves directly but generate a new iterator.
But our coffeeOrders object does---making it both an iterator and an iterable of itself.


🤓 The Takeaway (with Coffee!) ☕

"An Iterator is Just an Iterable of Itself" means:

  • An iterator must implement a next() method.
  • If Symbol.iterator returns the same object, it becomes an iterable as well.
  • The same object can both produce items and represent the collection being iterated over.

Final Thought: Coffee and JavaScript are Both Better When Shared!

Next time you wait in a coffee queue, remember:

  • The barista isn't just serving customers---they're also part of the system.
  • Just like an iterator that iterates over its own collection.

💬 Did this analogy help the concept click?
Drop a comment below and share your own JavaScript insights! 🚀


💡 Happy coding! 🔄☕

Top comments (0)