16

This works fine for me:

const iterable = [1, 2, 3];

for (const value of iterable) {
    console.log(value);
}

However this does not work:

const iterable = {1:10, 2:20, 3:30};

for (const value of iterable) {
    console.log(value);
    console.log(iterable[value]);
}

Instead giving me the error:

Uncaught TypeError: iterable[Symbol.iterator] is not a function(…)

How should I be doing this?

This is what I do now:

for(const value in iterable){
    if (iterable.hasOwnProperty(value)) {
        console.log(value);
        console.log(iterable[value]);
    }
}
Baz
  • 12,713
  • 38
  • 145
  • 268
  • 3
    Did you mean `for … in`? And no, the first example shouldn't "work" either. – Bergi Dec 16 '16 at 10:09
  • You shouldn't be doing this. Just use a `for…in` loop. You don't need the `.hasOwnProperty` check, btw. – Bergi Dec 16 '16 at 15:02

1 Answers1

21

for..of only works for iterable objects. You could implement an iterator like this:

const iterable = {
  [Symbol.iterator]() {
    return {
      i: 1,
      next() {
        if (this.i <= 3) {
          return { value: 10 * this.i++, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

for (const value of iterable2) {
    console.log(value);
} // 10, 20, 30

To iterate over plain objects, other than for...in which I think is fine, you could use Object.keys:

const iterable = {1:10, 2:20, 3:30};
Object.keys( iterable ).forEach( key => {
    console.log( iterable[key] );
});  // 10, 20, 30

BTW your first example throws a syntax error, maybe you meant const iterable = [1,2,3]? Then it would work since Arrays are iterable objects.

pawel
  • 35,827
  • 7
  • 56
  • 53
  • 24
    i feel top code is 5x less readable – Muhammad Umer Apr 09 '17 at 18:16
  • In the second example, if you don't care about `iterable`'s keys (1, 2, 3) but only its values (10, 20, 30), you can write `Object.values(iterable).forEach(value => console.log(value));` – Robin Métral Apr 03 '19 at 12:40
  • @robinmetral good point. I think at the time of writing this answer `Object.values` hasn't been as widely supported as it is now. – pawel Apr 03 '19 at 14:02
  • @pawel yes, `Object.values()` is somewhat new. Just mentioning it so that readers as of today will know there'y another way :) – Robin Métral Apr 04 '19 at 06:27