The iterator pattern is when you consume the values of a data source (could be a database, could be an array) one by one.
.next()
@@iterator
key, which is available with constant Symbol.iterator
[Symbol.iterator]
is a zero arguments function that returns an object conforming to the iterator protocolvalue
and done
. When the result becomes { value: undefined, done: true }
, you have iterated over every value in the iterable. There’s nothing left to iterate over at this point.String
, Array
, TypedArray
, Map
, Set
and array-like objects (arguments
or NodeList
). But NOT Object
. But you can create your own iterable object by implementing a .next()
method for itthe for...of
statement creates a loop iterating over built-in and user-defined iterable objects.
1for (variable of iterable) {
2 // do something
3}
You can use declare the variable with either var
, let
or const
1const iterable = [10, 20, 30];
2
3for (let value of iterable) {
4 value += 1;
5 console.log(value);
6}
7// 11
8// 21
9// 31
The Object
is not iterable, which is unfortunate because that’s the one we use the most, we build our own objects.
1// Objects are not iterable..
2var myObj = {
3 a: 1,
4 b: 2,
5 c: 3
6}
7
8for (let i of myObj) {
9 console.log(i) // TypeError: myObj is not iterable
10}
But, we can define our own iterators by implementing the iterator protocol, i.e. implementing a next()
method that returns at least the following two properties: value
and done
1var mySecondObj = {
2 a: 1,
3 b: 2,
4 c: 3,
5 [Symbol.iterator]: function(){ // the @@iterator property saved as the constant [Symbol.iterator]
6 let keys = Object.keys(this)
7 let index = 0
8 return {
9 next: () => (index < keys.length) ? // defining our own 'next' function to implement 'iterator protocol'
10 { done: false, value: this[keys[index++]]} :
11 { done: true, value: undefined}
12 }
13 }
14}
15console.log([...mySecondObj]) // [ 1, 2, 3 ]