JavaScript forEach vs for...in (arrays and objects)

Compare Array.prototype.forEach with for...in on objects and arrays, when for...of wins, and how to avoid enumerable-key bugs. Runnable Node snippets with short output notes.

Published

Updated

Read time 4 min read

Reviewed byDeepak Prasad

JavaScript forEach vs for...in (arrays and objects)

Array.prototype.forEach runs a callback once per array element in index order, while the for...in statement enumerates enumerable property names on any object—including arrays, where indexes look like keys and extra enumerable properties show up unexpectedly. Neither replaces the other: forEach is the array-centric API, for...in is for key introspection (often paired with guards). For a broader tour of looping styles—including for...of on iterables—see forEach vs for...in vs for...of in JavaScript.

Tested on: Node.js v20.18.2. A short note after each runnable snippet describes what you should see in the console.


Quick reference

ValuesforEach / for...of; keys on plain objects → for...in (+ Object.hasOwn when you skip inherited noise).

Goal Prefer
Act on each array element with a small callback array.forEach
Array values with break / continue / await for...of
Plain object enumerable keys for...in (+ Object.hasOwn if needed)
Only an object’s own keys as an array Object.keys, Object.entries

forEach — array elements with a callback

forEach is defined on arrays (and some typed arrays). It calls your function once per element, in index order, and passes (value, index, array). It always runs to completion unless the callback throws; there is no built-in break or continue.

javascript
const myArray = [1, 2, 3, 4, 5];
myArray.forEach(function (value) {
  console.log(value);
});
Output

You should see five lines: 1 through 5.

Use forEach when you already have a dense array and want a short, functional style for synchronous side effects (logging, mutating external state). For async work, prefer for...of with await instead of forEach.


for...in — enumerable string keys on an object

for...in assigns the property name (a string, or occasionally a Symbol in edge cases) on each iteration. For a plain object, that is exactly what you want for unknown keys.

javascript
const myObject = {
  name: "John Doe",
  age: 30,
  occupation: "Developer",
};

for (const property in myObject) {
  console.log(property + ": " + myObject[property]);
}
Output

You should see three lines: name: John Doe, age: 30, occupation: Developer.


Why for...in is a poor default for arrays

Arrays are objects. Their indices are enumerable properties, but arrays can also gain extra enumerable properties. for...in lists those keys too, while for...of walks iterator values (the actual elements).

javascript
const arr = [3, 5, 7];
Object.defineProperty(arr, "foo", {
  value: "hello",
  enumerable: true,
  configurable: true,
});
console.log("for...in keys:");
for (const i in arr) console.log(i);
console.log("for...of values:");
for (const v of arr) console.log(v);
Output

You should see keys 0, 1, 2, foo under for...in, but only values 3, 5, 7 under for...of.

So for “javascript each vs in” on array values, forEach and for...of match user intent; for...in matches key introspection. If you need both index and value safely, use arr.forEach((v, i) => …) or for (const [i, v] of arr.entries()). A longer tour of indexes appears in get index in for...of and related loops.


Sparse arrays — forEach skips holes

forEach visits only elements that exist; for...in only sees defined indices (still as string keys).

javascript
const sparse = [];
sparse[2] = "c";
console.log("forEach:");
sparse.forEach((v, i) => console.log(i, v));
console.log("for...in:");
for (const k in sparse) console.log(k, sparse[k]);
Output

You should see forEach: then 2 c, then for...in: then 2 c.


Inherited enumerable properties

for...in walks the prototype chain for enumerable keys unless you guard.

javascript
const proto = { inherited: 1 };
const o = Object.create(proto);
o.own = 2;
console.log("for...in (no guard):");
for (const k in o) console.log(k);
console.log("for...in + Object.hasOwn:");
for (const k in o) if (Object.hasOwn(o, k)) console.log(k);
Output

You should see own and inherited without the guard, then only own with Object.hasOwn.

Prefer Object.hasOwn(obj, key) over legacy obj.hasOwnProperty(key) when you filter for...in.


Summary

JavaScript each vs in is really forEach (array method) vs for...in (key enumerator). Use forEach or for...of for array values; reserve for...in for objects (and always consider Object.hasOwn). Know that for...in on arrays can surface non-index keys, and that forEach is a poor place for await if you care about order and completion.


Frequently Asked Questions

1. What is the difference between forEach and for...in in JavaScript?

forEach is a method on arrays that runs a callback for each element value. for...in loops over enumerable property names (string keys) of an object, which for arrays means index names—and any extra enumerable properties—not the values themselves.

2. Can I use for...in to loop through an array in JavaScript?

You usually should not rely on it for array elements. It iterates enumerable keys, including non-index properties you or libraries add, and inherited enumerable properties unless you filter with Object.hasOwn.

3. Is JavaScript forEach the same as jQuery each?

No. Array.prototype.forEach is built into JavaScript. jQuery's .each is a jQuery collection method with different rules; use forEach or for...of on plain arrays in modern code.

4. Can you break out of a forEach loop?

No. forEach always runs the callback for every element unless an exception is thrown. Use a for or for...of loop if you need break or continue.

5. Does await work inside forEach?

Not in the way people expect. forEach ignores the async callback's returned promise, so work may not finish before code after the loop runs. Use for...of with await for sequential async work.

6. What should I use instead of for...in for array values?

Use for...of for values, forEach for side effects with a callback, or a classic for loop when you need the index and flow control.

References

Array.prototype.forEach() - JavaScript | MDN
for...in - JavaScript | MDN
for...of - JavaScript | MDN
Loops and iteration - JavaScript | MDN

Olorunfemi Akinlua

Boasting over five years of experience in JavaScript, specializing in technical content writing and UX design. With a keen focus on programming languages, he crafts compelling content and designs …