I've been doing a lot of algorithm practice lately, and I just came across a quirk of how for...in works.
I love using JavaScript's for...in and for...of loops when iterating because I consider the code much cleaner and readable at a glance.
In this post, I'll be discussing a problem you may run into with for...in if you're trying to take shortcuts like I was.
What is for...in?
In case you're not familiar, here's a simple example of code side by side that will give the same console logs:
arr = [1, 2, 3]
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]) // 1, 2, 3
}
for(let i in arr) {
console.log(arr[i]) // 1, 2, 3
}
for(let el of arr) {
console.log(el) // 1, 2, 3
}
Like I said earlier, I consider the second/third to be "cleaner", but the second runs into issues if you need to use i
as a number. The following won't produce the same console logs:
arr = [1, 2, 3]
for (let i = 0; i < arr.length; i++) {
n = i + 5
console.log(n) // 6, 7, 8
}
for(let i in arr) {
n = i + 5
console.log(n) // "05", "15", "25"
}
The reason for this is because typeof i
in the for...in loop is a "string"
rather than a "number"
. This means you'll get weird results doing math on i
.
Conclusion
In summary, if you need to use the numerical value for the index as you loop over an array, you either need to use the long-form verbose/explicit for loop or add something like i = parseInt(i)
at the top of your loop:
arr = [1, 2, 3]
for (let i = 0; i < arr.length; i++) {
n = i + 5
console.log(n) // 6, 7, 8
}
for(let i in arr) {
i = parseInt(i)
n = i + 5
console.log(n) // 6, 7, 8
}
Edit: There have been a few other great suggestions on how to handle this in the comments! Check them out
Top comments (14)
You can also use
Array#keys
to get an iterator with the array indexes as numbers:Similarly,
Array#values
gives the elements of the array, andArray#entries
gives tuples of[index, element]
:Awesome! I didn't put 2 + 2 that
.keys()
and.entries()
would work on arrays (I use them all the time for objects), that's great.It's a little different from
Object.keys
and so on. You can doObject.keys(arr)
too, but then you'll get an array of string keys, rather than an iterator of number keys. Interestingly, there's no such thing asObject#keys
β I guess it doesn't make sense to return an iterator of keys for something that itself isn't iterable.Right, because they're class methods on Object that take a param, that's probably why I didn't think to look into how it could work with arrays. Very interesting.
An alternative that I didn't want to get into is using the index param from
arr.forEach
, but it is an option:It's informative and straight to point..
Also if possible can you change examples for "What is for...in?" as
Anyways..thanks for the information
Thanks for the extra info!
the reason for this is that βfor...inβ iterates over all the enumerable (own, not proto) properties of the object. this means that the array object (subject) will have its properties (index values) iterated over.
the reason they are a string is because all object properties are stored as strings. the properties of an array are indices which are presented as strings just as any other object properties.
you can use Object(arr).entries as the iterator which will give you [index, element] pairs in βfor...ofβ. because βfor...ofβ iterates over the elements themselves which will be those entry pairs.
Thanks for the extra details! Makes sense that is just like object properties note that you mention it
Good read ... who knows a mnemonic or aid to help remembering the difference between "for in" and "for of"? because I always forget which is which ...
Ah got it already - I think this would work:
for "I"n yields "I"ndexes
for "O"f yields "O"bjects
So "for In" yields the "I"ndexes (keys) of the elements, "for Of" yields the "O"bjects (the elements themselves) ... playing it a bit fast and loose, but you get the idea ;-)
super interesting read!
I only use map, reduce and foreach.
I havenβt heard of that as a way to convert to numbers. Iβll have to give it a shot when Iβm at a computer later!
For of?