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

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

I know what is for… in loop(it iterate over key), but heard the first time about for… of(it iterate over value). I am confused with for… of loop. I didn’t get adject. This is the code below :
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 is does not log “3”, “5”, “7”,”hello”
}

What I got is, for… of iterates over property values. then why it doesn’t log(return) “3”, “5”, “7”,”hello” instead of “3”, “5”, “7” ? but for… in loop iterate over each key (“0”, “1”, “2”, “foo”). here for… in loop also iterate over foo key. but for… of not iterarte over value of foo property ie “hello”.Why it is like that?
Long story in short:
here i console for… of loop. it should be log “3”, “5”, “7”,”hello” but here it logs “3”, “5”, “7”. Why ?
Example Link

Solutions/Answers:

Solution 1:

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).

Solution 2:

I find a complete answer at : https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html (Although it is for type script, this is 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"
}

Solution 3:

For…in loop

The for…in loop improves upon the weaknesses of the for loop by eliminating the counting logic and exit condition.

Example:

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

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

But, you still have to deal with the issue of using an index to access the values of the array, and that stinks; it almost makes it more confusing than before.

Also, the for…in loop can get you into big trouble when you need to add an extra method to an array (or another object). Because for…in loops loop over all enumerable properties, this means if you add any additional properties to the array’s prototype, then those properties will also appear in the loop.

Array.prototype.decimalfy = function() {
  for (let i = 0; i < this.length; i++) {
    this[i] = this[i].toFixed(2);
  }
};

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

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

Prints:

0

1

2

3

4

5

6

7

8

9

function() {
 for (let i = 0; i < this.length; i++) {
  this[i] = this[i].toFixed(2);
 }
}

This is why for…in loops are discouraged when looping over arrays.

NOTE: The forEach loop is another type of for loop in JavaScript.
However, forEach() is actually an array method, so it can only be used
exclusively with arrays. There is also no way to stop or break a
forEach loop. If you need that type of behavior in your loop, you’ll
have to use a basic for loop.

For…of loop

The for…of loop is used to loop over any type of data that is iterable.

Example:

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  console.log(digit);
}

Prints:

0

1

2

3

4

5

6

7

8

9

This makes the for…of loop the most concise version of all the for loops.

But wait, there’s more! The for…of loop also has some additional benefits that fix the weaknesses of the for and for…in loops.

You can stop or break a for…of loop at anytime.

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  if (digit % 2 === 0) {
    continue;
  }
  console.log(digit);
}

Prints:

1

3

5

7

9

And you don’t have to worry about adding new properties to objects. The for…of loop will only loop over the values in the object.

Solution 4:

The for-in statement iterates over the enumerable properties of an object, in arbitrary order.

The loop will iterate over all enumerable properties of the object itself and those the object inherits from its constructor’s prototype

You can think of it as “for in” basically iterates and list out all the keys.

var str = 'abc';
var arrForOf = [];
var arrForIn = [];

for(value of str){
  arrForOf.push(value);
}

for(value in str){
  arrForIn.push(value);
}

console.log(arrForOf); 
// ["a", "b", "c"]
console.log(arrForIn); 
// ["0", "1", "2", "formatUnicorn", "truncate", "splitOnLast", "contains"]

Solution 5:

The for...in statement iterates over the enumerable properties of an object, in an arbitrary order.
Enumerable properties are those properties whose internal [[Enumerable]] flag is set to true, hence if there is any enumerable property in the prototype chain, the for...in loop will iterate on those as well.

The for...of statement iterates over data that iterable object defines to be iterated over.

Example:

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];

for (let i in iterable) {
  console.log(i); // logs: 0, 1, 2, "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs: 0, 1, 2,
  }
}

for (let i of iterable) {
  console.log(i); // logs: 3, 5, 7
}

Like earlier, you can skip adding hasOwnProperty in for...of loops.

Solution 6:

There are some already defined data types which allows us to iterate over them easily e.g Array, Map, String Objects

Normal for in iterates over the iterator and in response provides us with the keys that are in the order of insertion as shown in below example.

  const numbers = [1,2,3,4,5];
   for(let number in number) {
     console.log(number);
   }

   // result: 0, 1, 2, 3, 4

Now if we try same with for of, then in response it provides us with the values not the keys. e.g

  const numbers = [1,2,3,4,5];
   for(let numbers of numbers) {
    console.log(number);
  }

  // result: 1, 2, 3, 4, 5

So looking at both of the iterators we can easily differentiate the difference between both of them.

Note:- For of only works with the Symbol.iterator

So if we try to iterate over normal object, then it will give us an error e.g-

const Room = {
   area: 1000,
   height: 7,
   floor: 2
 }

for(let prop in Room) {
 console.log(prop);
 } 

// Result area, height, floor

for(let prop of Room) {
  console.log(prop);
 } 

Room is not iterable

Now for iterating over we need to define an ES6 Symbol.iterator e.g

  const Room= {
    area: 1000, height: 7, floor: 2,
   [Symbol.iterator]: function* (){
    yield this.area;
    yield this.height;
    yield this.floors;
  }
}


for(let prop of Room) {
  console.log(prop);
 } 

//Result 1000, 7, 2

This is the difference between For in and For of. Hope that it might clear the difference.