For more tips like this, sign up to the weekly newsletter!

The difference between for..of and for..in

If you have an Array, the difference between using for..of and for..in seems minuscule:

const arr = [5, 6, 7];

for (let i in arr) {
  console.log(arr[i]); // 5, 6, 7
}

for (let i of arr) {
  console.log(i); // 5, 6, 7
}

The former loops over the indices, while the latter over the values.

Is that the only difference?

Far from it. In fact, they are entirely different, but for this particular case (iterating over a simple Array), they work similarly.

For..in

The for..in loop iterates over the object's enumerable properties. In case of a simple Array, these happen to be the indices of the elements.

But they work for Objects too:

const obj = {a: 1, b: 2};

for (let i in obj) {
  console.log(i); // a, b
}

What are enumerable properties?

All properties that are defined as enumerable for the object and all inherited ones of the same sort. Seems straightforward, but it can surprise you.

For example, NodeList has a few unexpected enumerable properties:

for(let i in document.querySelectorAll("div")) {
  console.log(i); // 0, 1, 2, ..., length, item, entries, forEach, keys, values
}

In short: they are sort of magic and can pop up even when you don't expect them.

Also, for..in does not guarantee any particular ordering. Depending on the use case, this can be a problem.

For..of

for..of, on the other hand, iterates over an iterable. In Javascript, an iterable is any object that defines a [Symbol.iterator] function that returns a conforming iterator. This lets the object define how to return its elements.

const iterable = {
  [Symbol.iterator]: function*() {
    yield 5;
    yield 6;
    yield 7;
  }
}
for (let i of iterable) {
  console.log(i); // 5, 6, 7
}
Conclusion

Don't use for..in, unless you know what you are doing.

Try it
References
Learn more: