for…in & for…of (JavaScript)

Having encountered both the for...in and for...of iterators in JavaScript, I never knew what the difference was. Today, however, I received an error in a for...in loop where it wasn’t outputting the correct number of results, and so finally looked up the difference. The main difference described on MDN is that for...in is used for iterating over enumerable properties of objects. That simply refers to objects that have properties with values that can be looked over. This can be like looking through an array (with indexes), a string (with indexes), or an Object (with keys) but not something like a boolean. The for...of iterator on the other hand serves iterable collections. This refers to objects whose enumerable properties can be followed in order. Arrays and strings still work because they use indexes, but an Object will not because there is no order to its keys.

Now with this knowledge, we can see how the two operations iterate over simple arrays differently. You can test this out by writing:

var array = ['a','b','c','d']
for (var i in array) {
console.log(i)
}
#=> 0
#=> 1
#=> 2
#=> 3

As you might have expected, this will just output the index of array. If you do the same, but with for...of , you would get:

for (var i of array) {
console.log(i)
}
#=> 'a'
#=> 'b'
#=> 'c'
#=> 'd'

This is because for...of iterates not over the enumerable properties of that array (its indexes) but, already knowing it as a collection, iterates over the values themselves. This leads to problems if trying to use for...of to iterate over an Object for instance:

var hash = {
'a': 1,
'b': 2
}
for (var i of hash) {
console.log(i)
}
#=> Uncaught TypeError: undefined is not a function

This problem comes from there being no ‘iterable collection’ existing in this object, and so for...of will not work. If you try for (var i in hash) , however, you would output a and b.

Another interesting part of for...of is that it can easily reach through nested values, like below:

var nestedArray = [['a', 1], ['b', 2], ['c', 3]]
for (var outer of nestedArray) {
console.log(outer)
}
#=> ['a', 1]
#=> ['b', 2]
#=> ['c', 3]
for (var [innerFirst, innerSecond] of nestedArray) {
console.log(innerFirst + " is:")
console.log(innerSecond)
}
#=> a is:
#=> 1
#=> b is:
#=> 2
#=> c is:
#=> 3

This is extremely useful if you are dealing with similar nested arrays and don’t want to create two for loops.

Another important difference between the two with regards to arrays is that for...in will immediately look for the first defined enumerable property, which can lead to strange situations in arrays like below, where it skips the first few indexes with undefined values. for...of will not do this, as it immediately looks for the first index (or first element of the iterable collection).

var array = []
array[5] = 'found me'
for (var i in array) {
console.log(array[i])
}
#=> found me

for (var i of array) {
console.log(i)
}
#=> undefined
#=> undefined
#=> undefined
#=> undefined
#=> undefined
#=> found me

So, as you can see here, for...in outputs only the first enumerable property with a value, which is index 5 of array , whereas for...of will look at the first index in that collection.

Feel free to keep experimenting to see how the two work, but now you can already start deciding for yourself which for... iterator you want to use!