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:
for..in iterates over all enumerable property keys of an object
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:
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.
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.
Here is a useful mnemonic for remembering the difference between for...in Loop and for...of Loop.
"index in, object of"
for...in Loop => iterates over the index in the array.
for...of Loop => iterates over the object of objects.
for of is used to iterate over iterables and for in is used to iterate over object properties
Here's a trick to remember:
for of is not for objects (so it's for iterables)
for in is not for iterables (so it's for objects)
Another trick:
for in returns object indices (keys) while for of returns values
//for in, iterates keys in an object and indexes in an array
let obj={a:1, b:2}
for( const key in obj)
console.log(obj[key]); //would print 1 and 2
console.log(key); //would print a and b
let arr = [10, 11, 12, 13];
for (const item in arr)
console.log(item); //would print 0 1 2 3
//for of, iterates values in an array or any iterable
let arr = [10, 11, 12, 13];
for (const item of arr )
console.log(item); //would print 10 11 12 13
Another difference between the two loops, which nobody has mentioned before:
Destructuring for...in is deprecated. Use for...of instead.
Source
So if we want to use destructuring in a loop, for get both index and value of each array element, we should to use the for...of loop with the Array method entries():
for (const [idx, el] of arr.entries()) {
console.log( idx + ': ' + el );
}
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.
Short answer: for...in loops over keys, while for...of loops over values.
for (let x in ['a', 'b', 'c', 'd'] {
console.log(x);
}
// Output
0
1
2
3
for (let x of ['a', 'b', 'c', 'd'] {
console.log(x);
}
// Output
a
b
c
d
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"]
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.
The for-in loop
for-in loop is used to traverse through enumerable properties of a collection, in an arbitrary order. A collection is a container type object whose items can be using an index or a key.
var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
var myString = "123";
console.log( myObject[ 'a' ], myArray[ 1 ], myString[ 2 ] );
for-in loop extracts the enumerable properties (keys) of a collection all at once and iterates over it one at a time. An enumerable property is the property of a collection that can appear in for-in loop.
By default, all properties of an Array and Object appear in for-in loop. However, we can use Object.defineProperty method to manually configure the properties of a collection.
var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
Object.defineProperty( myObject, 'd', { value: 4, enumerable: false } );
Object.defineProperty( myArray, 3, { value: 4, enumerable: false } );
for( var i in myObject ){ console.log( 'myObject:i =>', i ); }
for( var i in myArray ){ console.log( 'myArray:i =>', i ); }
In the above example, the property d of the myObject and the index 3 of myArray does not appear in for-in loop because they are configured with enumerable: false.
There are few issues with for-in loops. In the case of Arrays, for-in loop will also consider methods added on the array using myArray.someMethod = f syntax, however, myArray.length remains 4.
The for-of loop
It is a misconception that for-of loop iterate over the values of a collection. for-of loop iterates over an Iterable object. An iterable is an object that has the method with the name Symbol.iterator directly on it one on one of its prototypes.
Symbol.iterator method should return an Iterator. An iterator is an object which has a next method. This method when called return value and done properties.
When we iterate an iterable object using for-of loop, the Symbol.iterator the method will be called once get an iterator object. For every iteration of for-of loop, next method of this iterator object will be called until done returned by the next() call returns false. The value received by the for-of loop for every iteration if the value property returned by the next() call.
var myObject = { a: 1, b: 2, c: 3, d: 4 };
// make `myObject` iterable by adding `Symbol.iterator` function directlty on it
myObject[ Symbol.iterator ] = function(){
console.log( `LOG: called 'Symbol.iterator' method` );
var _myObject = this; // `this` points to `myObject`
// return an iterator object
return {
keys: Object.keys( _myObject ),
current: 0,
next: function() {
console.log( `LOG: called 'next' method: index ${ this.current }` );
if( this.current === this.keys.length ){
return { done: true, value: null }; // Here, `value` is ignored by `for-of` loop
} else {
return { done: false, value: _myObject[ this.keys[ this.current++ ] ] };
}
}
};
}
// use `for-of` loop on `myObject` iterable
for( let value of myObject ) {
console.log( 'myObject: value => ', value );
}
The for-of loop is new in ES6 and so are the Iterable and Iterables. The Array constructor type has Symbol.iterator method on its prototype. The Object constructor sadly doesn't have it but Object.keys(), Object.values() and Object.entries() methods return an iterable (you can use console.dir(obj) to check prototype methods). The benefit of the for-of loop is that any object can be made iterable, even your custom Dog and Animal classes.
The easy way to make an object iterable is by implementing ES6 Generator instead of custom iterator implementation.
Unlike for-in, for-of loop can wait for an async task to complete in each iteration. This is achieved using await keyword after for statement documentation.
Another great thing about for-of loop is that it has Unicode support. According to ES6 specifications, strings are stored with UTF-16 encoding. Hence, each character can take either 16-bit or 32-bit. Traditionally, strings were stored with UCS-2 encoding which has supports for characters that can be stored within 16 bits only.
Hence, String.length returns number of 16-bit blocks in a string. Modern characters like an Emoji character takes 32 bits. Hence, this character would return length of 2. for-in loop iterates over 16-bit blocks and returns the wrong index. However, for-of loop iterates over the individual character based on UTF-16 specifications.
var emoji = "😊🤣";
console.log( 'emoji.length', emoji.length );
for( var index in emoji ){ console.log( 'for-in: emoji.character', emoji[index] ); }
for( var character of emoji ){ console.log( 'for-of: emoji.character', character ); }
for...of loop works only with iterable objects. In JavaScript, iterables are objects which can be looped over.
String, Array, TypedArray, Map, and Set are all built-in iterables, because each of their prototype objects implements an ##iterator method. So, for...of loop works on the mentioned object types.
Object in JavaScript is not iterable by default. So, for...of loop does not work on objects.
In simple words, for...of works with strings and arrays but not with objects.
for...in works with those properties whose enumerable flag is set to true.
Enumerable flag for properties created via simple assignment or property initializer are by default true.
Enumerable flag for properties created via Object.defineProperty are by default false.
Here is a more detailed post with examples: https://dev.to/swastikyadav/difference-between-forof-and-forin-loop-in-javascript-j2o
A see a lot of good answers, but I decide to put my 5 cents just to have good example:
For in loop
iterates over all enumerable props
let nodes = document.documentElement.childNodes;
for (var key in nodes) {
console.log( key );
}
For of loop
iterates over all iterable values
let nodes = document.documentElement.childNodes;
for (var node of nodes) {
console.log( node.toString() );
}
When I first started out learning the for in and of loop, I was confused with my output too, but with a couple of research and understanding you can think of the individual loop like the following :
The
for...in loop returns the indexes of the individual property and has no effect of impact on the property's value, it loops and returns information on the property and not the value.
E.g
let profile = {
name : "Naphtali",
age : 24,
favCar : "Mustang",
favDrink : "Baileys"
}
The above code is just creating an object called profile, we'll use it for both our examples, so, don't be confused when you see the profile object on an example, just know it was created.
So now let us use the for...in loop below
for(let myIndex in profile){
console.log(`The index of my object property is ${myIndex}`)
}
// Outputs :
The index of my object property is 0
The index of my object property is 1
The index of my object property is 2
The index of my object property is 3
Now Reason for the output being that we have Four(4) properties in our profile object and indexing as we all know starts from 0...n, so, we get the index of properties 0,1,2,3 since we are working with the for..in loop.
for...of loop* can return either the property, value or both, Let's take a look at how.
In javaScript, we can't loop through objects normally as we would on arrays, so, there are a few elements we can use to access either of our choices from an object.
Object.keys(object-name-goes-here) >>> Returns the keys or properties of an object.
Object.values(object-name-goes-here) >>> Returns the values of an object.
Object.entries(object-name-goes-here) >>> Returns both the keys and values of an object.
Below are examples of their usage, pay attention to Object.entries() :
Step One: Convert the object to get either its key, value, or both.
Step Two: loop through.
// Getting the keys/property
Step One: let myKeys = ***Object.keys(profile)***
Step Two: for(let keys of myKeys){
console.log(`The key of my object property is ${keys}`)
}
// Getting the values of the property
Step One: let myValues = ***Object.values(profile)***
Step Two : for(let values of myValues){
console.log(`The value of my object property is ${values}`)
}
When using Object.entries() have it that you are calling two entries on the object, i.e the keys and values. You can call both by either of the entry. Example Below.
Step One: Convert the object to entries, using ***Object.entries(object-name)***
Step Two: **Destructure** the ***entries object which carries the keys and values***
like so **[keys, values]**, by so doing, you have access to either or both content.
// Getting the keys/property
Step One: let myKeysEntry = ***Object.entries(profile)***
Step Two: for(let [keys, values] of myKeysEntry){
console.log(`The key of my object property is ${keys}`)
}
// Getting the values of the property
Step One: let myValuesEntry = ***Object.entries(profile)***
Step Two : for(let [keys, values] of myValuesEntry){
console.log(`The value of my object property is ${values}`)
}
// Getting both keys and values
Step One: let myBothEntry = ***Object.entries(profile)***
Step Two : for(let [keys, values] of myBothEntry){
console.log(`The keys of my object is ${keys} and its value
is ${values}`)
}
Make comments on unclear parts section(s).
Everybody did explain why this problem occurs, but it's still very easy to forget about it and then scratching your head why you got wrong results. Especially when you're working on big sets of data when the results seem to be fine at first glance.
Using Object.entries you ensure to go trough all properties:
var arr = [3, 5, 7];
arr.foo = "hello";
for ( var [key, val] of Object.entries( arr ) ) {
console.log( val );
}
/* Result:
3
5
7
hello
*/
In simple terms forIN iterates over the KEYS IN the array(index)/object(key),
whereas forOF iterates over the VALUES OF the array(value).
Related
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:
for..in iterates over all enumerable property keys of an object
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:
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.
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.
Here is a useful mnemonic for remembering the difference between for...in Loop and for...of Loop.
"index in, object of"
for...in Loop => iterates over the index in the array.
for...of Loop => iterates over the object of objects.
for of is used to iterate over iterables and for in is used to iterate over object properties
Here's a trick to remember:
for of is not for objects (so it's for iterables)
for in is not for iterables (so it's for objects)
Another trick:
for in returns object indices (keys) while for of returns values
//for in, iterates keys in an object and indexes in an array
let obj={a:1, b:2}
for( const key in obj)
console.log(obj[key]); //would print 1 and 2
console.log(key); //would print a and b
let arr = [10, 11, 12, 13];
for (const item in arr)
console.log(item); //would print 0 1 2 3
//for of, iterates values in an array or any iterable
let arr = [10, 11, 12, 13];
for (const item of arr )
console.log(item); //would print 10 11 12 13
Another difference between the two loops, which nobody has mentioned before:
Destructuring for...in is deprecated. Use for...of instead.
Source
So if we want to use destructuring in a loop, for get both index and value of each array element, we should to use the for...of loop with the Array method entries():
for (const [idx, el] of arr.entries()) {
console.log( idx + ': ' + el );
}
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.
Short answer: for...in loops over keys, while for...of loops over values.
for (let x in ['a', 'b', 'c', 'd'] {
console.log(x);
}
// Output
0
1
2
3
for (let x of ['a', 'b', 'c', 'd'] {
console.log(x);
}
// Output
a
b
c
d
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"]
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.
The for-in loop
for-in loop is used to traverse through enumerable properties of a collection, in an arbitrary order. A collection is a container type object whose items can be using an index or a key.
var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
var myString = "123";
console.log( myObject[ 'a' ], myArray[ 1 ], myString[ 2 ] );
for-in loop extracts the enumerable properties (keys) of a collection all at once and iterates over it one at a time. An enumerable property is the property of a collection that can appear in for-in loop.
By default, all properties of an Array and Object appear in for-in loop. However, we can use Object.defineProperty method to manually configure the properties of a collection.
var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
Object.defineProperty( myObject, 'd', { value: 4, enumerable: false } );
Object.defineProperty( myArray, 3, { value: 4, enumerable: false } );
for( var i in myObject ){ console.log( 'myObject:i =>', i ); }
for( var i in myArray ){ console.log( 'myArray:i =>', i ); }
In the above example, the property d of the myObject and the index 3 of myArray does not appear in for-in loop because they are configured with enumerable: false.
There are few issues with for-in loops. In the case of Arrays, for-in loop will also consider methods added on the array using myArray.someMethod = f syntax, however, myArray.length remains 4.
The for-of loop
It is a misconception that for-of loop iterate over the values of a collection. for-of loop iterates over an Iterable object. An iterable is an object that has the method with the name Symbol.iterator directly on it one on one of its prototypes.
Symbol.iterator method should return an Iterator. An iterator is an object which has a next method. This method when called return value and done properties.
When we iterate an iterable object using for-of loop, the Symbol.iterator the method will be called once get an iterator object. For every iteration of for-of loop, next method of this iterator object will be called until done returned by the next() call returns false. The value received by the for-of loop for every iteration if the value property returned by the next() call.
var myObject = { a: 1, b: 2, c: 3, d: 4 };
// make `myObject` iterable by adding `Symbol.iterator` function directlty on it
myObject[ Symbol.iterator ] = function(){
console.log( `LOG: called 'Symbol.iterator' method` );
var _myObject = this; // `this` points to `myObject`
// return an iterator object
return {
keys: Object.keys( _myObject ),
current: 0,
next: function() {
console.log( `LOG: called 'next' method: index ${ this.current }` );
if( this.current === this.keys.length ){
return { done: true, value: null }; // Here, `value` is ignored by `for-of` loop
} else {
return { done: false, value: _myObject[ this.keys[ this.current++ ] ] };
}
}
};
}
// use `for-of` loop on `myObject` iterable
for( let value of myObject ) {
console.log( 'myObject: value => ', value );
}
The for-of loop is new in ES6 and so are the Iterable and Iterables. The Array constructor type has Symbol.iterator method on its prototype. The Object constructor sadly doesn't have it but Object.keys(), Object.values() and Object.entries() methods return an iterable (you can use console.dir(obj) to check prototype methods). The benefit of the for-of loop is that any object can be made iterable, even your custom Dog and Animal classes.
The easy way to make an object iterable is by implementing ES6 Generator instead of custom iterator implementation.
Unlike for-in, for-of loop can wait for an async task to complete in each iteration. This is achieved using await keyword after for statement documentation.
Another great thing about for-of loop is that it has Unicode support. According to ES6 specifications, strings are stored with UTF-16 encoding. Hence, each character can take either 16-bit or 32-bit. Traditionally, strings were stored with UCS-2 encoding which has supports for characters that can be stored within 16 bits only.
Hence, String.length returns number of 16-bit blocks in a string. Modern characters like an Emoji character takes 32 bits. Hence, this character would return length of 2. for-in loop iterates over 16-bit blocks and returns the wrong index. However, for-of loop iterates over the individual character based on UTF-16 specifications.
var emoji = "😊🤣";
console.log( 'emoji.length', emoji.length );
for( var index in emoji ){ console.log( 'for-in: emoji.character', emoji[index] ); }
for( var character of emoji ){ console.log( 'for-of: emoji.character', character ); }
for...of loop works only with iterable objects. In JavaScript, iterables are objects which can be looped over.
String, Array, TypedArray, Map, and Set are all built-in iterables, because each of their prototype objects implements an ##iterator method. So, for...of loop works on the mentioned object types.
Object in JavaScript is not iterable by default. So, for...of loop does not work on objects.
In simple words, for...of works with strings and arrays but not with objects.
for...in works with those properties whose enumerable flag is set to true.
Enumerable flag for properties created via simple assignment or property initializer are by default true.
Enumerable flag for properties created via Object.defineProperty are by default false.
Here is a more detailed post with examples: https://dev.to/swastikyadav/difference-between-forof-and-forin-loop-in-javascript-j2o
A see a lot of good answers, but I decide to put my 5 cents just to have good example:
For in loop
iterates over all enumerable props
let nodes = document.documentElement.childNodes;
for (var key in nodes) {
console.log( key );
}
For of loop
iterates over all iterable values
let nodes = document.documentElement.childNodes;
for (var node of nodes) {
console.log( node.toString() );
}
When I first started out learning the for in and of loop, I was confused with my output too, but with a couple of research and understanding you can think of the individual loop like the following :
The
for...in loop returns the indexes of the individual property and has no effect of impact on the property's value, it loops and returns information on the property and not the value.
E.g
let profile = {
name : "Naphtali",
age : 24,
favCar : "Mustang",
favDrink : "Baileys"
}
The above code is just creating an object called profile, we'll use it for both our examples, so, don't be confused when you see the profile object on an example, just know it was created.
So now let us use the for...in loop below
for(let myIndex in profile){
console.log(`The index of my object property is ${myIndex}`)
}
// Outputs :
The index of my object property is 0
The index of my object property is 1
The index of my object property is 2
The index of my object property is 3
Now Reason for the output being that we have Four(4) properties in our profile object and indexing as we all know starts from 0...n, so, we get the index of properties 0,1,2,3 since we are working with the for..in loop.
for...of loop* can return either the property, value or both, Let's take a look at how.
In javaScript, we can't loop through objects normally as we would on arrays, so, there are a few elements we can use to access either of our choices from an object.
Object.keys(object-name-goes-here) >>> Returns the keys or properties of an object.
Object.values(object-name-goes-here) >>> Returns the values of an object.
Object.entries(object-name-goes-here) >>> Returns both the keys and values of an object.
Below are examples of their usage, pay attention to Object.entries() :
Step One: Convert the object to get either its key, value, or both.
Step Two: loop through.
// Getting the keys/property
Step One: let myKeys = ***Object.keys(profile)***
Step Two: for(let keys of myKeys){
console.log(`The key of my object property is ${keys}`)
}
// Getting the values of the property
Step One: let myValues = ***Object.values(profile)***
Step Two : for(let values of myValues){
console.log(`The value of my object property is ${values}`)
}
When using Object.entries() have it that you are calling two entries on the object, i.e the keys and values. You can call both by either of the entry. Example Below.
Step One: Convert the object to entries, using ***Object.entries(object-name)***
Step Two: **Destructure** the ***entries object which carries the keys and values***
like so **[keys, values]**, by so doing, you have access to either or both content.
// Getting the keys/property
Step One: let myKeysEntry = ***Object.entries(profile)***
Step Two: for(let [keys, values] of myKeysEntry){
console.log(`The key of my object property is ${keys}`)
}
// Getting the values of the property
Step One: let myValuesEntry = ***Object.entries(profile)***
Step Two : for(let [keys, values] of myValuesEntry){
console.log(`The value of my object property is ${values}`)
}
// Getting both keys and values
Step One: let myBothEntry = ***Object.entries(profile)***
Step Two : for(let [keys, values] of myBothEntry){
console.log(`The keys of my object is ${keys} and its value
is ${values}`)
}
Make comments on unclear parts section(s).
Everybody did explain why this problem occurs, but it's still very easy to forget about it and then scratching your head why you got wrong results. Especially when you're working on big sets of data when the results seem to be fine at first glance.
Using Object.entries you ensure to go trough all properties:
var arr = [3, 5, 7];
arr.foo = "hello";
for ( var [key, val] of Object.entries( arr ) ) {
console.log( val );
}
/* Result:
3
5
7
hello
*/
In simple terms forIN iterates over the KEYS IN the array(index)/object(key),
whereas forOF iterates over the VALUES OF the array(value).
I can use Array() to have an array with a fixed number of undefined entries. For example
Array(2); // [empty × 2]
But if I go and use the map method, say, on my new array, the entries are still undefined:
Array(2).map( () => "foo"); // [empty × 2]
If I copy the array then map does work:
[...Array(2)].map( () => "foo"); // ["foo", "foo"]
Why do I need a copy to use the array?
When you use Array(arrayLength) to create an array, you will have:
a new JavaScript array with its length property set to that number (Note: this implies an array of arrayLength empty slots, not slots with actual undefined values).
The array does not actually contain any values, not even undefined values - it simply has a length property.
When you spread an iterable object with a length property into an array, spread syntax accesses each index and sets the value at that index in the new array. For example:
const arr1 = [];
arr1.length = 4;
// arr1 does not actually have any index properties:
console.log('1' in arr1);
const arr2 = [...arr1];
console.log(arr2);
console.log('2' in arr2);
And .map only maps properties/values for which the property actually exists in the array you're mapping over.
Using the array constructor is confusing. I would suggest using Array.from instead, when creating arrays from scratch - you can pass it an object with a length property, as well as a mapping function:
const arr = Array.from(
{ length: 2 },
() => 'foo'
);
console.log(arr);
The reason is that the array element is unassigned. See here the first paragraph of the description. ... callback is invoked only for indexes of the array which have assigned values, including undefined.
Consider:
var array1 = Array(2);
array1[0] = undefined;
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(array1);
console.log(map1);
Outputs:
Array [undefined, undefined]
Array [NaN, undefined]
When the array is printed each of its elements are interrogated. The first has been assigned undefined the other is defaulted to undefined.
The mapping operation calls the mapping operation for the first element because it has been defined (through assignment). It does not call the mapping operation for the second argument, and simply passes out undefined.
As pointed out by #CertainPerformance, your array doesn't have any properties besides its length, you can verify that with this line: new Array(1).hasOwnProperty(0), which returns false.
Looking at 15.4.4.19 Array.prototype.map you can see, at 7.3, there's a check whether a key exists in the array.
1..6. [...]
7. Repeat,
while k < len
Let
Pk be ToString(k).
Let
kPresent be the result of calling the [[HasProperty]]
internal method of O with argument Pk.
If
kPresent is true, then
Let
kValue be the result of calling the [[Get]] internal
method of O with argument Pk.
Let
mappedValue be the result of calling the [[Call]] internal
method of callbackfn with T as the this
value and argument list containing kValue, k, and
O.
Call
the [[DefineOwnProperty]] internal method of A with
arguments Pk, Property Descriptor {[[Value]]: mappedValue,
[[Writable]]: true, [[Enumerable]]: true,
[[Configurable]]: true}, and false.
Increase
k by 1.
9. Return A.
As pointed out already, Array(2) will only create an array of two empty slots which cannot be mapped over.
As far as some and every are concerned, Array(2) is indeed an empty array:
Array(2).some(() => 1 > 0); //=> false
Array(2).every(() => 1 < 0); //=> true
However this array of empty slots can somehow be "iterated" on:
[].join(','); //=> ''
Array(2).join(','); //=> ','
JSON.stringify([]) //=> '[]'
JSON.stringify(Array(2)) //=> '[null,null]'
So we can take that knowledge to come up with interesting and somewhat ironic ways to use ES5 array functions on such "empty" arrays.
You've come up with that one yourself:
[...Array(2)].map(foo);
A variation of a suggestion from #charlietfl:
Array(2).fill().map(foo);
Personally I'd recommend this one:
Array.from(Array(2)).map(foo);
A bit old school:
Array.apply(null, Array(2)).map(foo);
This one is quite verbose:
Array(2).join(',').split(',').map(foo);
An external API returns a JSON result of the following form:
{
"data": {
"1.0": 'foo',
"2.3": 'bar',
"3.6": 'baz'
}
}
Here, the keys "1.0", "2.3", "3.6" should really be taken as strings denoting a discrete categorisation, not as values along a continuous axis. It is therefore perfectly valid for this API to return these keys as strings.
However... (you can feel it coming, aren't you?)
In the JS client, I need to iterate over these keys and here comes the trouble:
the browser's JS engine automatically casted all these keys into Number
using Object.keys(myObject.data) returns... strings!
therefore, the following does not work at all as you can see:
let myObject = {
"data": {
"1.0": 'foo',
"2.3": 'bar',
"3.6": 'baz'
}
}
console.log(myObject.data)
for (let k in Object.keys(myObject.data)) {
console.log(k, myObject.data[k])
}
// {
// 1.0: 'foo',
// 2.3: 'bar',
// 3.6: 'baz
// }
// "1.0" undefined
// "2.3" undefined
// "3.6" undefined
It seems that we have two conflicting things here: first, the object keys are converted into Numbers, but at the same time, Object.keys() returns Strings instead of Numbers.
Is there an appropriate way to solve this problem?
Ideally, I'd like the object's actual keys to remain strings, as they should be. Casting the values from Object.keys() into Numbers would lead to quite cumbersome workarounds as the API can (and does) return "real" strings as keys sometimes (like { "red": 'foo', "blue": 'bar' }.
Your problem is for in
for in tries to access keys in array created by Object.keys(obj.data) which is actually index
let obj = {"data": {"1.0": 'foo',"2.3": 'bar',"3.6": 'baz'}}
Object.keys(obj.data).forEach(e=>{
console.log(typeof e)
})
//You can simply drop of Object.keys
for (let k in obj.data) {
console.log(k, obj.data[k])
}
Simply do not use Object.keys:
let myObject = {
"data": {
"1.0": 'foo',
"2.3": 'bar',
"3.6": 'baz'
}
}
console.log(myObject.data)
for (let k in myObject.data) {
console.log(k, myObject.data[k])
}
Some explanation:
Object.keys does what it says - extracts keys from the passed in object and returns them as array (in your case that'd be: [ "1.0", "2.3", "3.6"]). So when you are trying to loop over this with for..in, you are in fact looping over that resulting array, instead of the actual object and key variable will receive an index of the corresponding item from the array (0 for "1.0", 1 for "2.3", etc). That's just how for..in works. If you would like to loop over the values of the array instead, you could use for..of as another option. Or in your case, as I've mentioned above, simply do not use Object.keys.
The problem is with the for..in loop, try for..of to solve this issue. The for..in loop will iterate over all enumerable properties of the object itself and those the object inherits from its constructor's prototype.
Whereas for..of on the other hand, is mainly interested in values of iterable objects in this case it is an array returned by the Object.keys() call.
var myObject = {
"data": {
"1.0": 'foo',
"2.3": 'bar',
"3.6": 'baz'
}
}
console.log(myObject.data)
for (let k of Object.keys(myObject.data)) {
console.log(k, myObject.data[k])
}
Here when you are iterating through the Object.keys(myObject.data), it is considering the indices(keys of array object) of the returned array instead of the actual values of myObject.data array.
Here is the distinction with a small example:
var arr = [10, 20, 30];
console.log("**for - in loop**")
//logs indices 0, 1, 2
for (i in arr){
console.log(i);
}
console.log("**for - of loop**")
//logs values in the array 10, 20, 30
for (i of arr){
console.log(i);
}
I have an object 'obj'. Let's say we don't know where it came from, for a moment.
If I do
console.log(JSON.stringify(obj));
I obtain
[{"foo":101,"bar":1,"foobar":0},{"foo":102,"bar":1,"foobar":0}]
What kind of object is this?
I'm asking for I see two behaviours I can't understand:
1) It seems to be an array of objects (?) so I would expect
console.log(obj[0])
to return:
{"foo":101,"bar":1,"foobar":0},{"foo":102,"bar":1,"foobar":0}
instead it returns:
{"foo":101,"bar":1,"foobar":0}
2) I would expect
for (var somevar in obj){
console.log(JSON.stringify(somevar));
}
to return
first step: {"foo":101,"bar":1,"foobar":0}
second step: {"foo":102,"bar":1,"foobar":0}
instead it returns
first step: "0"
second step: "1"
Can someone explain me the nature of this object and why these two cases (expecially the second) return such results?
The obj is array or objects. It has two objects at index 0 and 1 that is why when you do console.log(obj[0]); it gives you only {"foo":101,"bar":1,"foobar":0}. Which is the object at index 0.
For second question, the for (var somevar in obj) loops over each key of obj and since it is a array data type the keys of the array is always its index value. That is why you get 0 and 1 in console. To make that work you need to do var somevar of obj in the for that will then consider the value and not the key of obj array.
var obj = [{"foo":101,"bar":1,"foobar":0},{"foo":102,"bar":1,"foobar":0}];
for (var somevar of obj){
console.log(JSON.stringify(somevar));
}
For your particular first problem - When we access an array by its index it returns value of that particular index. e.g
var first_array = ['A', 'B', 'C', 'D'];
var secound_array = [{"foo":101,"bar":1,"foobar":0},{"foo":102,"bar":1,"foobar":0}];
Syntex to access array data with index is array_variable[index], where index is numeric value. for e.g.
first_array[0] // output = A
first_array[2] //output = C
secound_array[0] // output = {"foo":101,"bar":1,"foobar":0}
This is your first problem solution because you are accessing an element by array index. Index of an array starts from 0.
For your second problem, the for..in statement iterates with the index, not the value. If I write like below code -
for (var somevar in secound_array){
console.log(JSON.stringify(somevar));
}
the output is
first step: 0
second step: 1
If you want output like
first step: {"foo":101,"bar":1,"foobar":0}
second step: {"foo":102,"bar":1,"foobar":0}
You need to write like below code -
for (var somevar of secound_array){
console.log(JSON.stringify(secound_array[somevar])); // here somevar is index of the item
}
For more info click here
You can also check for...of. e.g.
for (let o of secound_array) {
console.log(o)
}
To the first question:
You have two elements in your array:
var obj =
[
{"foo": 101, "bar":1, "foobar": 0}, //first element at index 0
{"foo": 102, "bar":1, "foobar": 0} //second element at index 1
];
console.log(obj[0]);
If you write console.log(obj[0]); then you get first element and not 2 elements at once because at index 0 you have only one element. And this is correct.
To the second question:
var obj = [{"foo": 101, "bar":1, "foobar": 0},{"foo": 102, "bar":1, "foobar": 0}];
for (var somevar in obj){
console.log(JSON.stringify(somevar));
}
This put in the console:
At first step: "0"
At second step: "1"
And this is correct too. For your wish you have to use for of loop and not for in because for in gives you the index of an element and not an element like for of.
Check the difference between for in and for of:
var arr = [ 3, 5, 7 ];
for(var i in arr) {
console.log(i); // 0, 1, 2
}
console.log('-----');
for(var i of arr) {
console.log(i); // 3, 5, 7
}
Arrays are objects in JavaScript. So that behavior is totally expected. The indices are keys to an array.
So when you do
console.log(obj[0])
You simply access the first item in the array
Then in the second case you are simply logging out the stringified keys '0' and '1'
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:
for..in iterates over all enumerable property keys of an object
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:
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.
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.
Here is a useful mnemonic for remembering the difference between for...in Loop and for...of Loop.
"index in, object of"
for...in Loop => iterates over the index in the array.
for...of Loop => iterates over the object of objects.
for of is used to iterate over iterables and for in is used to iterate over object properties
Here's a trick to remember:
for of is not for objects (so it's for iterables)
for in is not for iterables (so it's for objects)
Another trick:
for in returns object indices (keys) while for of returns values
//for in, iterates keys in an object and indexes in an array
let obj={a:1, b:2}
for( const key in obj)
console.log(obj[key]); //would print 1 and 2
console.log(key); //would print a and b
let arr = [10, 11, 12, 13];
for (const item in arr)
console.log(item); //would print 0 1 2 3
//for of, iterates values in an array or any iterable
let arr = [10, 11, 12, 13];
for (const item of arr )
console.log(item); //would print 10 11 12 13
Another difference between the two loops, which nobody has mentioned before:
Destructuring for...in is deprecated. Use for...of instead.
Source
So if we want to use destructuring in a loop, for get both index and value of each array element, we should to use the for...of loop with the Array method entries():
for (const [idx, el] of arr.entries()) {
console.log( idx + ': ' + el );
}
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.
Short answer: for...in loops over keys, while for...of loops over values.
for (let x in ['a', 'b', 'c', 'd'] {
console.log(x);
}
// Output
0
1
2
3
for (let x of ['a', 'b', 'c', 'd'] {
console.log(x);
}
// Output
a
b
c
d
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"]
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.
The for-in loop
for-in loop is used to traverse through enumerable properties of a collection, in an arbitrary order. A collection is a container type object whose items can be using an index or a key.
var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
var myString = "123";
console.log( myObject[ 'a' ], myArray[ 1 ], myString[ 2 ] );
for-in loop extracts the enumerable properties (keys) of a collection all at once and iterates over it one at a time. An enumerable property is the property of a collection that can appear in for-in loop.
By default, all properties of an Array and Object appear in for-in loop. However, we can use Object.defineProperty method to manually configure the properties of a collection.
var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
Object.defineProperty( myObject, 'd', { value: 4, enumerable: false } );
Object.defineProperty( myArray, 3, { value: 4, enumerable: false } );
for( var i in myObject ){ console.log( 'myObject:i =>', i ); }
for( var i in myArray ){ console.log( 'myArray:i =>', i ); }
In the above example, the property d of the myObject and the index 3 of myArray does not appear in for-in loop because they are configured with enumerable: false.
There are few issues with for-in loops. In the case of Arrays, for-in loop will also consider methods added on the array using myArray.someMethod = f syntax, however, myArray.length remains 4.
The for-of loop
It is a misconception that for-of loop iterate over the values of a collection. for-of loop iterates over an Iterable object. An iterable is an object that has the method with the name Symbol.iterator directly on it one on one of its prototypes.
Symbol.iterator method should return an Iterator. An iterator is an object which has a next method. This method when called return value and done properties.
When we iterate an iterable object using for-of loop, the Symbol.iterator the method will be called once get an iterator object. For every iteration of for-of loop, next method of this iterator object will be called until done returned by the next() call returns false. The value received by the for-of loop for every iteration if the value property returned by the next() call.
var myObject = { a: 1, b: 2, c: 3, d: 4 };
// make `myObject` iterable by adding `Symbol.iterator` function directlty on it
myObject[ Symbol.iterator ] = function(){
console.log( `LOG: called 'Symbol.iterator' method` );
var _myObject = this; // `this` points to `myObject`
// return an iterator object
return {
keys: Object.keys( _myObject ),
current: 0,
next: function() {
console.log( `LOG: called 'next' method: index ${ this.current }` );
if( this.current === this.keys.length ){
return { done: true, value: null }; // Here, `value` is ignored by `for-of` loop
} else {
return { done: false, value: _myObject[ this.keys[ this.current++ ] ] };
}
}
};
}
// use `for-of` loop on `myObject` iterable
for( let value of myObject ) {
console.log( 'myObject: value => ', value );
}
The for-of loop is new in ES6 and so are the Iterable and Iterables. The Array constructor type has Symbol.iterator method on its prototype. The Object constructor sadly doesn't have it but Object.keys(), Object.values() and Object.entries() methods return an iterable (you can use console.dir(obj) to check prototype methods). The benefit of the for-of loop is that any object can be made iterable, even your custom Dog and Animal classes.
The easy way to make an object iterable is by implementing ES6 Generator instead of custom iterator implementation.
Unlike for-in, for-of loop can wait for an async task to complete in each iteration. This is achieved using await keyword after for statement documentation.
Another great thing about for-of loop is that it has Unicode support. According to ES6 specifications, strings are stored with UTF-16 encoding. Hence, each character can take either 16-bit or 32-bit. Traditionally, strings were stored with UCS-2 encoding which has supports for characters that can be stored within 16 bits only.
Hence, String.length returns number of 16-bit blocks in a string. Modern characters like an Emoji character takes 32 bits. Hence, this character would return length of 2. for-in loop iterates over 16-bit blocks and returns the wrong index. However, for-of loop iterates over the individual character based on UTF-16 specifications.
var emoji = "😊🤣";
console.log( 'emoji.length', emoji.length );
for( var index in emoji ){ console.log( 'for-in: emoji.character', emoji[index] ); }
for( var character of emoji ){ console.log( 'for-of: emoji.character', character ); }
for...of loop works only with iterable objects. In JavaScript, iterables are objects which can be looped over.
String, Array, TypedArray, Map, and Set are all built-in iterables, because each of their prototype objects implements an ##iterator method. So, for...of loop works on the mentioned object types.
Object in JavaScript is not iterable by default. So, for...of loop does not work on objects.
In simple words, for...of works with strings and arrays but not with objects.
for...in works with those properties whose enumerable flag is set to true.
Enumerable flag for properties created via simple assignment or property initializer are by default true.
Enumerable flag for properties created via Object.defineProperty are by default false.
Here is a more detailed post with examples: https://dev.to/swastikyadav/difference-between-forof-and-forin-loop-in-javascript-j2o
A see a lot of good answers, but I decide to put my 5 cents just to have good example:
For in loop
iterates over all enumerable props
let nodes = document.documentElement.childNodes;
for (var key in nodes) {
console.log( key );
}
For of loop
iterates over all iterable values
let nodes = document.documentElement.childNodes;
for (var node of nodes) {
console.log( node.toString() );
}
When I first started out learning the for in and of loop, I was confused with my output too, but with a couple of research and understanding you can think of the individual loop like the following :
The
for...in loop returns the indexes of the individual property and has no effect of impact on the property's value, it loops and returns information on the property and not the value.
E.g
let profile = {
name : "Naphtali",
age : 24,
favCar : "Mustang",
favDrink : "Baileys"
}
The above code is just creating an object called profile, we'll use it for both our examples, so, don't be confused when you see the profile object on an example, just know it was created.
So now let us use the for...in loop below
for(let myIndex in profile){
console.log(`The index of my object property is ${myIndex}`)
}
// Outputs :
The index of my object property is 0
The index of my object property is 1
The index of my object property is 2
The index of my object property is 3
Now Reason for the output being that we have Four(4) properties in our profile object and indexing as we all know starts from 0...n, so, we get the index of properties 0,1,2,3 since we are working with the for..in loop.
for...of loop* can return either the property, value or both, Let's take a look at how.
In javaScript, we can't loop through objects normally as we would on arrays, so, there are a few elements we can use to access either of our choices from an object.
Object.keys(object-name-goes-here) >>> Returns the keys or properties of an object.
Object.values(object-name-goes-here) >>> Returns the values of an object.
Object.entries(object-name-goes-here) >>> Returns both the keys and values of an object.
Below are examples of their usage, pay attention to Object.entries() :
Step One: Convert the object to get either its key, value, or both.
Step Two: loop through.
// Getting the keys/property
Step One: let myKeys = ***Object.keys(profile)***
Step Two: for(let keys of myKeys){
console.log(`The key of my object property is ${keys}`)
}
// Getting the values of the property
Step One: let myValues = ***Object.values(profile)***
Step Two : for(let values of myValues){
console.log(`The value of my object property is ${values}`)
}
When using Object.entries() have it that you are calling two entries on the object, i.e the keys and values. You can call both by either of the entry. Example Below.
Step One: Convert the object to entries, using ***Object.entries(object-name)***
Step Two: **Destructure** the ***entries object which carries the keys and values***
like so **[keys, values]**, by so doing, you have access to either or both content.
// Getting the keys/property
Step One: let myKeysEntry = ***Object.entries(profile)***
Step Two: for(let [keys, values] of myKeysEntry){
console.log(`The key of my object property is ${keys}`)
}
// Getting the values of the property
Step One: let myValuesEntry = ***Object.entries(profile)***
Step Two : for(let [keys, values] of myValuesEntry){
console.log(`The value of my object property is ${values}`)
}
// Getting both keys and values
Step One: let myBothEntry = ***Object.entries(profile)***
Step Two : for(let [keys, values] of myBothEntry){
console.log(`The keys of my object is ${keys} and its value
is ${values}`)
}
Make comments on unclear parts section(s).
Everybody did explain why this problem occurs, but it's still very easy to forget about it and then scratching your head why you got wrong results. Especially when you're working on big sets of data when the results seem to be fine at first glance.
Using Object.entries you ensure to go trough all properties:
var arr = [3, 5, 7];
arr.foo = "hello";
for ( var [key, val] of Object.entries( arr ) ) {
console.log( val );
}
/* Result:
3
5
7
hello
*/
In simple terms forIN iterates over the KEYS IN the array(index)/object(key),
whereas forOF iterates over the VALUES OF the array(value).