What is the difference between ( for... in ) and ( for... of ) statements?

I know what is a for... in loop (it iterates over the keys), but I have heard about for... of for the first time (it iterates over values).

I am confused about for... of loop.

var arr = [3, 5, 7];
arr.foo = "hello";
    
for (var i in arr) {
  console.log(i); // logs "0", "1", "2", "foo"
}
    
for (var i of arr) {
  console.log(i); // logs "3", "5", "7"
  // it doesn't log "3", "5", "7", "hello"
}

I understand that for... of iterates over property values. Then why doesn't it log "3", "5", "7", "hello" instead of "3", "5", "7"?

Unlike for... in loop, which iterates over each key ("0", "1", "2", "foo") and also iterates over the foo key, the for... of does not iterate over the value of foo property, i.e., "hello". Why it is like that?

Here I console for... of loop. It should log "3", "5", "7","hello" but it logs "3", "5", "7". Why?

Example Link


for in loops over enumerable property names of an object.

for of (new in ES6) does use an object-specific iterator and loops over the values generated by that.

In your example, the array iterator does yield all the values in the array (ignoring non-index properties).


I found a complete answer at Iterators and Generators (Although it is for TypeScript, this is the same for JavaScript too)

Both for..of and for..in statements iterate over lists; the values iterated on are different though, for..in returns a list of keys on the object being iterated, whereas for..of returns a list of values of the numeric properties of the object being iterated.

Here is an example that demonstrates this distinction:

let list = [4, 5, 6];

for (let i in list) {
   console.log(i); // "0", "1", "2",
}

for (let i of list) {
   console.log(i); // "4", "5", "6"
}

Another distinction is that for..in operates on any object; it serves as a way to inspect properties on this object. for..of on the other hand, is mainly interested in values of iterable objects. Built-in objects like Map and Set implement Symbol.iterator property allowing access to stored values.

let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";

for (let pet in pets) {
   console.log(pet); // "species"
}

for (let pet of pets) {
    console.log(pet); // "Cat", "Dog", "Hamster"
}

Difference for..in and for..of:

Both for..in and for..of are looping constructs which are used to iterate over data structures. The only difference between them is the entities they iterate over:

  1. for..in iterates over all enumerable property keys of an object
  2. for..of iterates over the values of an iterable object. Examples of iterable objects are arrays, strings, and NodeLists.

Example:

let arr = ['el1', 'el2', 'el3'];

arr.addedProp = 'arrProp';

// elKey are the property keys
for (let elKey in arr) {
  console.log(elKey);
}

// elValue are the property values
for (let elValue of arr) {
  console.log(elValue)
}

In this example we can observe that the for..in loop iterates over the keys of the object, which is an array object in this example. The keys are 0, 1, 2 (which correspond to the array elements) and addedProp. This is how the arr array object looks in chrome devtools:

enter image description here

You see that our for..in loop does nothing more than simply iterating over these keys.


The for..of loop in our example iterates over the values of a data structure. The values in this specific example are 'el1', 'el2', 'el3'. The values which an iterable data structure will return using for..of is dependent on the type of iterable object. For example an array will return the values of all the array elements whereas a string returns every individual character of the string.