Given an object range={a:1,b:2,c:3}
How can we iterate through this object?
It is not possible since objects are not iterable therefore we can't use for .. of loop and spread operator, and if we try, it gives us this error:
TypeError: Found non-callable @@iterator
When we use for .. of loop with objects, its @@iterator method is called. Yet, objects do not have a built-in iterator method like arrays and strings. Therefore, we need to implement the default iterator by ourselves.
To do that we need to add an attribute Symbol.iterator containing a function specifying how to iterate through this object which gets called when we iterate through the object and must return an iterator
Iterator is simply an object that contains a next() method that returns an object, this object has two attributes :
- done: a boolean specifying if we reach the last value or not.
- value: specifying the next value in the iteration.
And before that, we need to retrieve different values of objects with Object.values() to be returned and the length of object to check if we get to the last value and index specifying the current value.
The function is illustrated in the code below.
range[Symbol.iterator] = function () {
let values = Object.values(this);
let index = 0;
let length = values.length;
return {
next: () => {
return index < length
? { done: false, value: values[index++] }
: { done: true, value: undefined };
},
};
};
Now we are able to iterate through this object through for .. of loop and spread operator.
console.log(...range);
// 1 5 6 8
for (let x of range) {
console.log(x);
}
//1
//5
//6
//8
More details:
Symbol.Iterator: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator
Iterator protocol: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol
Top comments (6)
Nice - I'd never implemented iterator by hand before. I'd say
Object.entries|values|keys
is more effective in terms of loc. Is there any reason why you'd use iterator over the Object methods?With .entries you get access to your keys too.
This quick article is just to show the source of "TypeError: Found non-callable @@iterator" error and why we can't use for..of loop and spread operator with objects
You can use:
This is not the case for iterators, I would use different example if you want showcase them.
Interisting, I haven't heard about it
What about the for...in loop? Wasn't it designed specifically to allow one to iterate through object keys?
developer.mozilla.org/en-US/docs/W...
Of course, this article is about for.. of loop and spread operator which work only with iterable types