CodeBlanks Logo Icon CodeBlanks

Summary - Iterators

JavaScript course · Advanced · Lesson 47/100

Build a number-range iterable object using Symbol.iterator.

Summary - Iterators

In this group you learned the iterator protocol, the iterable protocol and how to write a custom iterator. An iterator returns { value, done } from next(). An object becomes iterable when you add [Symbol.iterator]; it then works with for...of, spread and destructuring.

When writing a custom iterator you keep state with let and keep it alive in next() via closure. Every [Symbol.iterator] call produces a fresh iterator; so the same iterable can be traversed independently multiple times.

Tips and common pitfalls

Once an iterator is exhausted, calling next() again keeps returning { value: undefined, done: true }; no error is thrown. To start a new loop, use the iterable, not the iterator; iterators are one-shot.

Do not mix up for...in and for...of: the former walks object keys, the latter walks values. Also null and undefined are not iterable; for...of throws on them.

Exercise Stepped number range

Write a function called makeRange(start, end, step). The function should return an iterable object: its [Symbol.iterator] method starts with let current = start and returns an iterator. The iterator's next() method returns { value, done: false } while current <= end, advancing current by step each step; otherwise it returns { value: undefined, done: true }. Then create a range with makeRange(1, 10, 2), log the numbers with for...of, and spread it into an array with [...range] to log its length.

Show example solution
function makeRange(start, end, step) {
  return {
    [Symbol.iterator]() {
      let current = start;
      return {
        next() {
          if (current <= end) {
            const value = current;
            current += step;
            return { value, done: false };
          }
          return { value: undefined, done: true };
        }
      };
    }
  };
}
const range = makeRange(1, 10, 2);
for (const num of range) {
  console.log(num);
}
const arr = [...range];
console.log(arr.length);

Test yourself

  1. What must you add to make an object iterable?

    • A toString method
    • A [Symbol.iterator] method
    • A length property
    • A valueOf method
    Show answer

    A [Symbol.iterator] method — Correct. Adding [Symbol.iterator] makes the object iterable.

  2. Make makeRange iterable

    function makeRange(start, end, step) {
      return {
        ____() {
          let current = start;
          return {
            next() {
              if (end >= current) {
                const value = current;
                current += step;
                return { value, done: false };
              }
              return { value: undefined, done: true };
            }
          };
        }
      };
    }
    Show answer
    function makeRange(start, end, step) {
      return {
        [Symbol.iterator]() {
          let current = start;
          return {
            next() {
              if (end >= current) {
                const value = current;
                current += step;
                return { value, done: false };
              }
              return { value: undefined, done: true };
            }
          };
        }
      };
    }

All lessons in Advanced