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)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay