for...in vs. for...of in JavaScript

Hero image for For...in vs. for...of in JavaScript. Image by Pawel Czerwinski.
Hero image for 'For...in vs. for...of in JavaScript.' Image by Pawel Czerwinski.

for...in and for...of look similar enough that beginners often use them interchangeably at first. That usually works right up until the loop gives them keys when they expected values, or it starts iterating over an object in a way they did not intend.

The difference is simple once you say it cleanly:

  • for...in iterates over property keys
  • for...of iterates over values from an iterable

That one line explains most of the confusion around them.


for...in gives you keys

If you use for...in, the loop variable receives a property key.

With an object, that is often exactly what you want:

const user = {  name: 'Sophie',  role: 'Editor',};for (const key in user) {  console.log(key);}

That logs:

  • name
  • role

The important point is that the loop gives you the key, not the value.

If you want the value as well, you use the key to access it:

for (const key in user) {  console.log(user[key as keyof typeof user]);}

for...of gives you values from iterables

for...of is different. It works with iterables such as arrays and gives you the values directly.

const roles = ['Editor', 'Admin', 'Reader'];for (const role of roles) {  console.log(role);}

That logs the actual array values:

  • Editor
  • Admin
  • Reader

This is why for...of usually feels more natural for arrays. Most of the time, when developers loop an array, they want the values rather than the index keys.


Arrays are Where Beginners Usually Make the Wrong Choice

Using for...in on an array technically works, but it gives you the index keys as strings.

const roles = ['Editor', 'Admin', 'Reader'];for (const index in roles) {  console.log(index);}

That logs:

  • 0
  • 1
  • 2

If you were expecting the role values, that is immediately confusing.

You can still get the values by indexing back into the array:

for (const index in roles) {  console.log(roles[index]);}

but that is exactly why for...of usually reads better for arrays:

for (const role of roles) {  console.log(role);}

Objects and Arrays are Not Symmetrical Here

This is the deeper pattern worth noticing.

For arrays:

  • for...of is usually the more natural fit

For plain objects:

  • for...in can work, because objects have keys rather than iterable values in the same sense

That mismatch is where new developers often stumble. They assume the two loops are just stylistic variations, but in practice they are aimed at different shapes of data.


Why for...of does not work on plain objects by default

Plain objects are not iterable by default.

That means this does not work:

const user = {  name: 'Sophie',  role: 'Editor',};for (const value of user) {  console.log(value);}

If you want to use for...of with objectlike data, you usually turn the object into an iterable structure first with helpers such as Object.keys, Object.values, or Object.entries.

for (const value of Object.values(user)) {  console.log(value);}

That is one reason these loops are not interchangeable. for...of depends on iterability, not on the generic idea of "something with properties".


for...in can include inherited keys

This is another reason for...in deserves a bit of caution.

for...in iterates over enumerable keys, including inherited ones if they are part of the chain being exposed that way.

That means it is not always the best tool when you only want an object's own keys.

In those cases, methods such as Object.keys() are often clearer because they make the boundary more explicit.

This is not a reason to fear for...in, but it is a reason to use it with some understanding rather than treating it as a generic catchall loop.


for...of usually communicates intent better for arrays

If you are working with arrays and you want each item, for...of tends to be the more readable choice.

const items = ['bread', 'milk', 'tea'];for (const item of items) {  console.log(item);}

That reads almost like plain English.

If you need the index as well, then a regular indexed loop or methods such as entries() can become more useful.

Again, the key is not to treat one loop as universally better. It is to match the loop to the data shape and the thing you need from it.


A Quick Side‑By‑Side Example

const colours = ['red', 'green', 'blue'];

Using for...in:

for (const index in colours) {  console.log(index);  // '0', '1', '2'}

Using for...of:

for (const colour of colours) {  console.log(colour);  // 'red', 'green', 'blue'}

That sidebyside comparison explains the difference more clearly than any amount of vague advice.


The Best Question to Ask

When choosing between these loops, ask:

"Do I want keys, or do I want values?"

If you want keys, for...in may be appropriate.

If you want values from an iterable, for...of is usually the right fit.

That is a much better decision rule than trying to remember one as "old" and the other as "modern" or anything similarly fuzzy.


Wrapping up

for...in and for...of differ because they iterate different things. for...in gives you property keys. for...of gives you iterable values. Once that distinction is clear, it becomes much easier to choose the right loop for arrays, objects, and other data structures without getting surprised by the result.

Key Takeaways

  • for...in iterates over keys.
  • for...of iterates over values from iterables.
  • Arrays usually read more clearly with for...of.
  • Plain objects work more naturally with keys unless you convert them with Object.keys, Object.values, or Object.entries.
  • Many loop bugs come from choosing a keyoriented loop when you really wanted values.

Once you focus on whether the loop should yield keys or values, the naming confusion around these two forms becomes much easier to manage.


Categories:

  1. Development
  2. Front‑End Development
  3. Guides
  4. JavaScript