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
// 3
As 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 undefined
for-of
loop[]
array destrcuturing pattern...
spread operator