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
Values → forEach / 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.
const myArray = [1, 2, 3, 4, 5];
myArray.forEach(function (value) {
console.log(value);
});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.
const myObject = {
name: "John Doe",
age: 30,
occupation: "Developer",
};
for (const property in myObject) {
console.log(property + ": " + myObject[property]);
}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).
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);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).
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]);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.
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);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?
2. Can I use for...in to loop through an array in JavaScript?
3. Is JavaScript forEach the same as jQuery each?
4. Can you break out of a forEach loop?
5. Does await work inside forEach?
6. What should I use instead of for...in for array values?
References
Array.prototype.forEach() - JavaScript | MDN
for...in - JavaScript | MDN
for...of - JavaScript | MDN
Loops and iteration - JavaScript | MDN
