DEV Community

Cover image for How to iterate through objects in JAVASCRIPT ?
Hssan Bouzlima
Hssan Bouzlima

Posted on

How to iterate through objects in JAVASCRIPT ?

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 };
    },
  };
}; 
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Latest comments (6)

Collapse
 
jcubic profile image
Jakub T. Jankiewicz

You can use:

for ([key, value] of Object.entries(range)) {
   console.log(`${key}: ${value}`);
}
Enter fullscreen mode Exit fullscreen mode

This is not the case for iterators, I would use different example if you want showcase them.

Collapse
 
jenbutondevto profile image
Jen

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?

const range = { a: 1, b: 2, c: 5, d: 8 }
console.log(...Object.values(range))
// 1 2 5 8
Enter fullscreen mode Exit fullscreen mode

With .entries you get access to your keys too.

console.log(...Object.values(range))
// [ 'a', 1 ] [ 'b', 2 ] [ 'c', 5 ] [ 'd', 8 ]
Enter fullscreen mode Exit fullscreen mode
Collapse
 
hssanbzlm profile image
Hssan Bouzlima

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

Collapse
 
duplicated profile image
Duplicated

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...

Collapse
 
hssanbzlm profile image
Hssan Bouzlima

Of course, this article is about for.. of loop and spread operator which work only with iterable types

Collapse
 
madrafj profile image
Ahmad Rafsanjani

Interisting, I haven't heard about it