As ES6 introduced new syntax, it also introduced new protocols, these protocols can be implemented by any object respecting some conventions.
iterable protocol allows javascript objects to define or customize their iteration behavior such as what values are looped over in a for .. of construct.
some types has built-in interation behavior, this means that you can directly contrcut for .. of on these types example:
- Array
- Map
- String
const myArray = [1,2,3];
for(const num of myArray) {
console.log(num);
}
// 1
// 2
// 3As we can see in this example myArray (of type Array) has a built-in iteration behavior
An example of non iterable type is Object, but we can make an Object iterable by implementing @@iterator method, this means that the Object or its prototype needs to have a property with key @@iterator this is available via a constant Symbol.iterator
Symbol.iterator is a zero argument function that returns an object, conforming to the iterator protocol
Iterator protocol defines a standard way to produce a sequence of values, an object is iterator when it implements a next() method with the following semantics
- 0 argument function
next()that returns an object - The returned object should contain 2 properties
done(Boolean) andvalue(Any javascript type value)
As we discussed for an object to be iterable it has to contain a property with key Symbol.iterator that contains a 0 argument function, where that function should return an iterator Object that contains next() method, where that method returns an Object that contains value and done properties :D !!!
let numbersIterable = {};
// After implementing `Symbol.iterator` numbersIterable became iterable object
numbersIterable[Symbol.iterator] = function() {
let number = 0;
// This returned object is called iterator object
return {
next: function() {
if(number < 10) {
return { done: false, value: ++number };
} else {
return { done: true };
}
}
}
}
// for..of is introduced in ES6 and it is a consumer to iterables, you can't use for..of on non iterable objects
// Since we change `numberIterable` to be iterable now we can use for..of
for(let num of numbersIterable) {
console.log(num);
}As we can see from example 14.1 we had to create iterator object to make numberIterable iterable, but it is very important to differentiate between iterable and iterator, in the next example we will create iterator
let numbersIterator = function(max) {
let number = 0;
return {
next: function() {
if(number < max) {
return { done: false, value: ++number };
} else {
return { done: true };
}
}
}
}
const myNumbersIterator = numbersIterator(6);
while (true) {
const current = myNumbersIterator.next();
console.log(current.value);
if (current.done) {
break;
}
}
// 1 2 3 4 5 6 undefinedfor-ofloop[]array destrcuturing pattern...spread operator