Suggest an editImprove this articleRefine the answer for “Iterator”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**An iterator is an object with a `next()` method that returns the next element of a sequence each time it is called, in the form `{ value, done }`.** While there is something left to give, `done` is `false`, and once the sequence is exhausted you get `{ value: undefined, done: true }` and the walk stops. An iterator should not be confused with an iterable: an iterable is an object that has a `[Symbol.iterator]()` method which creates an iterator. That method is what the engine calls automatically for `for...of`, the spread operator `...`, `Array.from()` and destructuring. The built-in `Array`, `String`, `Map`, `Set`, `arguments`, `NodeList` and typed arrays are iterable, while a plain object `{}` is not. The simplest way to create an iterator is a `function*` generator. ```javascript const it = ['a', 'b'][Symbol.iterator](); console.log(it.next()); // { value: 'a', done: false } console.log(it.next()); // { value: 'b', done: false } console.log(it.next()); // { value: undefined, done: true } ``` **Key point:** an iterator hands out values one at a time through `next()`, while an iterable knows how to create such an iterator through `[Symbol.iterator]()`.Shown above the full answer for quick recall.Answer (EN)Image**An iterator is an object that returns the elements of some sequence one by one on every call to its `next()` method.** Formally: an iterator is an object implementing a `next()` method that returns an object of the shape `{ value: any, done: boolean }`. ## Theory ### TL;DR - An iterator is an object with a `next()` method that returns `{ value, done }`. - When `done: true` the iteration is over, and `value` is usually `undefined` at that point. - An iterable is an object that has a `[Symbol.iterator]()` method returning an iterator. - `for...of`, spread `...`, `Array.from()` and destructuring all work through exactly this protocol. - Built-in iterables: `Array`, `String`, `Map`, `Set`, `arguments`, `NodeList`, typed arrays. - A `function*` generator creates an iterator automatically, with no manual `return { value, done }`. ### Quick example ```javascript function createIterator(arr) { let i = 0; return { next() { if (i < arr.length) { return { value: arr[i++], done: false }; } else { return { value: undefined, done: true }; } } }; } const iterator = createIterator(['a', 'b', 'c']); console.log(iterator.next()); // { value: 'a', done: false } console.log(iterator.next()); // { value: 'b', done: false } console.log(iterator.next()); // { value: 'c', done: false } console.log(iterator.next()); // { value: undefined, done: true } ``` When `done: true`, the iteration ends. ### What an iterator does inside `for...of` When you write: ```javascript for (const item of ['a', 'b', 'c']) { console.log(item); } ``` JavaScript does roughly the following under the hood: ```javascript const iterable = ['a', 'b', 'c']; const iterator = iterable[Symbol.iterator](); // creates an iterator while (true) { const { value, done } = iterator.next(); if (done) break; console.log(value); } ``` In other words, the loop itself knows nothing about arrays: it only knows the `next()` protocol. ### Iterables and `Symbol.iterator` An object is **iterable** if it has the method: ```javascript obj[Symbol.iterator]() ``` which returns an **iterator**. `Symbol.iterator` is a special symbol that defines the "iterability" of an object, and JavaScript calls that method automatically whenever an object has to be walked. Examples of built-in iterable structures: - `Array` - `String` - `Map` - `Set` - `arguments` - `NodeList` (in the browser) - `TypedArray` Your own iterable is written like this: ```javascript const range = { from: 1, to: 4, [Symbol.iterator]() { let current = this.from; let last = this.to; return { next() { if (current <= last) { return { value: current++, done: false }; } else { return { done: true }; } } }; } }; for (const num of range) { console.log(num); // 1, 2, 3, 4 } ``` When JavaScript meets `for...of`, it calls `range[Symbol.iterator]()` and uses the iterator it gets back. A string is iterable too, and it is walked by code points rather than by bytes: ```javascript const str = 'Hi'; const iterator = str[Symbol.iterator](); console.log(iterator.next()); // { value: 'H', done: false } console.log(iterator.next()); // { value: 'i', done: false } console.log(iterator.next()); // { value: undefined, done: true } ``` ### Iterators with spread, destructuring and `Array.from` All of these constructs **use an iterator internally**: ```javascript const set = new Set([1, 2, 3]); console.log([...set]); // [1, 2, 3] console.log(Array.from(set)); // [1, 2, 3] const [a, b] = set; console.log(a, b); // 1 2 ``` That is exactly why spread works with `Set` and `Map` even though they are not arrays: having `[Symbol.iterator]()` is enough. ### Generators are automatic iterators A generator (`function*`) is a function that creates an iterator by itself. ```javascript function* numbers() { yield 1; yield 2; yield 3; } const iterator = numbers(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true } ``` And also: ```javascript for (const n of numbers()) { console.log(n); // 1, 2, 3 } ``` Generators are convenient because you do not have to write `return { value, done }` by hand: the engine builds those objects from each `yield` for you. Iterability of modern structures: | Structure | Iterable? | Returns | | --- | --- | --- | | `Array` | yes | values | | `String` | yes | characters | | `Map` | yes | `[key, value]` pairs | | `Set` | yes | values | | `Object` | no | nothing, but you can add `[Symbol.iterator]()` by hand | | `arguments` | yes | the argument values | A short summary: | Term | Description | | --- | --- | | **Iterator** | An object with a `next()` method returning `{ value, done }` | | **Iterable** | An object that has a `[Symbol.iterator]()` method | | `Symbol.iterator` | The symbol pointing at the method that creates an iterator | | **Used in** | `for...of`, spread, `Array.from`, destructuring | | **Generator (`function*`)** | A simplified way to create an iterator | ### Common mistakes - **Confusing an iterator with an iterable.** An iterator has `next()`, an iterable has `[Symbol.iterator]()`. An array is an iterable, while `arr[Symbol.iterator]()` is already an iterator. - **Expecting `for...of` to work on a plain object.** `{}` has no `[Symbol.iterator]()`, so you get a `TypeError`. For objects you use `Object.keys()`, `Object.values()` or `Object.entries()`. - **Walking the same iterator twice.** It is single-use: after `{ done: true }` it is exhausted forever, and a second `for...of` yields nothing. - **Forgetting to return `{ value, done }` as an object.** If `next()` returns a bare value, the engine throws a `TypeError`. - **Mixing up `for...of` and `for...in`.** `for...in` walks keys, inherited ones included, and has nothing to do with the iteration protocol. - **Writing an unbounded iterable with no limit.** A generator with `while (true)` inside a `for...of` with no `break` and no `take` will freeze the tab.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.