How to loop through a plain JavaScript object with the objects as members

JavascriptLoops

Javascript Problem Overview


How can I loop through all members in a JavaScript object, including values that are objects?

For example, how could I loop through this (accessing the "your_name" and "your_message" for each)?

var validation_messages = {
    "key_1": {
        "your_name": "jimmy",
        "your_msg": "hello world"
    },
    "key_2": {
        "your_name": "billy",
        "your_msg": "foo equals bar"
    }
}

Javascript Solutions


Solution 1 - Javascript

for (var key in validation_messages) {
	// skip loop if the property is from prototype
	if (!validation_messages.hasOwnProperty(key)) continue;

	var obj = validation_messages[key];
	for (var prop in obj) {
		// skip loop if the property is from prototype
		if (!obj.hasOwnProperty(prop)) continue;

		// your code
		alert(prop + " = " + obj[prop]);
	}
}

Solution 2 - Javascript

Under ECMAScript 5, you can combine Object.keys() and Array.prototype.forEach():

var obj = {
  first: "John",
  last: "Doe"
};

//
//	Visit non-inherited enumerable keys
//
Object.keys(obj).forEach(function(key) {

  console.log(key, obj[key]);

});

Solution 3 - Javascript

In ES6/2015 you can loop through an object like this (using the arrow function):

Object.keys(myObj).forEach(key => {
  console.log(key);        // the name of the current key.
  console.log(myObj[key]); // the value of the current key.
});

JS Bin

In ES7/2016 you can use Object.entries instead of Object.keys and loop through an object like this:

Object.entries(myObj).forEach(([key, val]) => {
  console.log(key); // the name of the current key.
  console.log(val); // the value of the current key.
});

The above would also work as a one-liner:

Object.entries(myObj).forEach(([key, val]) => console.log(key, val));

jsbin

In case you want to loop through nested objects as well, you can use a recursive function (ES6):

const loopNestedObj = obj => {
  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === "object") loopNestedObj(obj[key]); // recurse.
    else console.log(key, obj[key]); // or do something with key and val.
  });
};

JS Bin

The same as function above, but with ES7 Object.entries() instead of Object.keys():

const loopNestedObj = obj => {
  Object.entries(obj).forEach(([key, val]) => {
    if (val && typeof val === "object") loopNestedObj(val); // recurse.
    else console.log(key, val); // or do something with key and val.
  });
};

Here we loop through nested objects change values and return a new object in one go using Object.entries() combined with Object.fromEntries() (ES10/2019):

const loopNestedObj = obj =>
  Object.fromEntries(
    Object.entries(obj).map(([key, val]) => {
      if (val && typeof val === "object") [key, loopNestedObj(val)]; // recurse
      else [key, updateMyVal(val)]; // or do something with key and val.
    })
  );

Another way of looping through objects is by using for ... in and for ... of. See vdegenne's nicely written answer.

Solution 4 - Javascript

The problem with this

for (var key in validation_messages) {
   var obj = validation_messages[key];
   for (var prop in obj) {
      alert(prop + " = " + obj[prop]);
   }
}

is that you’ll also loop through the primitive object's prototype.

With this one you will avoid it:

for (var key in validation_messages) {
   if (validation_messages.hasOwnProperty(key)) {
      var obj = validation_messages[key];
      for (var prop in obj) {
         if (obj.hasOwnProperty(prop)) {
            alert(prop + " = " + obj[prop]);
         }
      }
   }
}

Solution 5 - Javascript

Using Underscore.js’s _.each:

_.each(validation_messages, function(value, key){
    _.each(value, function(value, key){
        console.log(value);
    });
});

Solution 6 - Javascript

If you use recursion you can return object properties of any depth-

function lookdeep(object){
	var collection= [], index= 0, next, item;
	for(item in object){
		if(object.hasOwnProperty(item)){
			next= object[item];
			if(typeof next== 'object' && next!= null){
				collection[index++]= item +
				':{ '+ lookdeep(next).join(', ')+'}';
			}
			else collection[index++]= [item+':'+String(next)];
		}
	}
	return collection;
}

//example

var O={
	a:1, b:2, c:{
		c1:3, c2:4, c3:{
			t:true, f:false
		}
	},
	d:11
};
var lookdeepSample= 'O={'+ lookdeep(O).join(',\n')+'}';


/*  returned value: (String)
O={
	a:1, 
	b:2, 
	c:{
		c1:3, c2:4, c3:{
			t:true, f:false
		}
	},
	d:11
}

*/

Solution 7 - Javascript

> This answer is an aggregate of the solutions that were provided in this > post with some performance feedbacks. I think there is two > use cases and the OP didn't mention if he needs to access the keys in order use them > during the loop process.

I. The keys need to be accessed

✔ The of and Object.keys approach

let k;
for (k of Object.keys(obj)) {

    /*        k : key
     *   obj[k] : value
     */
}

✔ The in approach

let k;
for (k in obj) {

    /*        k : key
     *   obj[k] : value
     */
}

Use this one with caution, as it could print prototype'd properties of obj

✔ The ES7 approach

for (const [key, value] of Object.entries(obj)) {

}

However, at the time of the edit I wouldn't recommend the ES7 method, because JavaScript initializes a lot of variables internally to build this procedure (see the feedbacks for proof). Unless you are not developing a huge application which deserves optimization, then it is OK, but if optimization is your priority, you should think about it.

II. We just need to access each value

✔ The of and Object.values approach

let v;
for (v of Object.values(obj)) {

}

More feedbacks about the tests:

  • Caching Object.keys or Object.values performance is negligible

For instance,

const keys = Object.keys(obj);
let i;
for (i of keys) {
  //
}
// same as
for (i of Object.keys(obj)) {
  //
}
  • For Object.values case, using a native for loop with cached variables in Firefox seems to be a little faster than using a for...of loop. However, the difference is not that important and Chrome is running for...of faster than native for loop, so I would recommend to use for...of when dealing with Object.values in any cases (4th and 6th tests).

  • In Firefox, the for...in loop is really slow, so when we want to cache the key during the iteration it is better to use Object.keys. Plus Chrome is running both structure at equal speed (first and last tests).

You can check the tests here: https://jsperf.com/es7-and-misc-loops

Solution 8 - Javascript

for(var k in validation_messages) {
    var o = validation_messages[k];
    do_something_with(o.your_name);
    do_something_else_with(o.your_msg);
}

Solution 9 - Javascript

An optimized and improved version of AgileJon's answer:

var key, obj, prop, owns = Object.prototype.hasOwnProperty;

for (key in validation_messages ) {

    if (owns.call(validation_messages, key)) {

        obj = validation_messages[key];

        for (prop in obj ) {

            // Using obj.hasOwnProperty might cause you headache if there is
            // obj.hasOwnProperty = function(){return false;}
            // but 'owns' will always work
            if (owns.call(obj, prop)) {
                console.log(prop, "=", obj[prop]);
            }
        }
    }
}

Solution 10 - Javascript

p is the value

for (var key in p) {
  alert(key + ' => ' + p[key]);
}

OR

Object.keys(p).forEach(key => { console.log(key, p[key]) })

Solution 11 - Javascript

In ES7 you can do:

for (const [key, value] of Object.entries(obj)) {
  //
}

Solution 12 - Javascript

for(var key in validation_messages){
    for(var subkey in validation_messages[key]){
        //code here
        //subkey being value, key being 'yourname' / 'yourmsg'
    }
}

Solution 13 - Javascript

A few ways to do that...

1) A two-layer for...in loop...

for (let key in validation_messages) {
   const vmKeys = validation_messages[key];
   for (let vmKey in vmKeys) {
      console.log(vmKey + vmKeys[vmKey]);
   }
}

2) Using Object.key

Object.keys(validation_messages).forEach(key => {
   const vmKeys = validation_messages[key];
   Object.keys(vmKeys).forEach(key => {
    console.log(vmKeys + vmKeys[key]);
   });
});

3) Recursive function

const recursiveObj = obj => {
  for(let key in obj){
    if(!obj.hasOwnProperty(key)) continue;

    if(typeof obj[key] !== 'object'){
      console.log(key + obj[key]);
    } else {
      recursiveObj(obj[key]);
    }
  }
}

And call it like:

recursiveObj(validation_messages);

Solution 14 - Javascript

Another option:

var testObj = {test: true, test1: false};
for(let x of Object.keys(testObj)){
    console.log(x);
}

Solution 15 - Javascript

Here comes the improved and recursive version of AgileJon's solution (demo):

function loopThrough(obj){
  for(var key in obj){
    // skip loop if the property is from prototype
    if(!obj.hasOwnProperty(key)) continue;
    
    if(typeof obj[key] !== 'object'){
      //your code
      console.log(key+" = "+obj[key]);
    } else {
      loopThrough(obj[key]);
    }
  }
}
loopThrough(validation_messages);

This solution works for all kinds of different depths.

Solution 16 - Javascript

ECMAScript 2017, just finalized a month ago, introduces Object.values(). So now you can do this:

let v;
for (v of Object.values(validation_messages))
   console.log(v.your_name);   // jimmy billy

Solution 17 - Javascript

var validation_messages = {
    "key_1": {
        "your_name": "jimmy",
        "your_msg": "hello world"
    },
    "key_2": {
        "your_name": "billy",
        "your_msg": "foo equals bar"
    }
}
for (var i in validation_messages) {
    console.log("i = \"" + i + "\"");
    console.log("validation_messages[\"" + i + "\"] = ");
    console.log(validation_messages[i]);
    console.log("\n");
    for (var j in validation_messages[i]) {
        console.log("j = \"" + j + "\"");
        console.log("validation_messages[\"" + i + "\"][\"" + j + "\"] = \"" + validation_messages[i][j] + "\"");
        console.log("\n");
    }
    console.log('\n');
}

Outputs:

i = "key_1"
validation_messages["key_1"] = 
{
  your_name:"jimmy",
  your_msg:"hello world"
}

j = "your_name"
validation_messages["key_1"]["your_name"] = "jimmy"

j = "your_msg"
validation_messages["key_1"]["your_msg"] = "hello world"


i = "key_2"
validation_messages["key_2"] = 
{
  your_name:"billy",
  your_msg:"foo equals bar"
}

j = "your_name"
validation_messages["key_2"]["your_name"] = "billy"

j = "your_msg"
validation_messages["key_2"]["your_msg"] = "foo equals bar"

Solution 18 - Javascript

I couldn't get the previous answere to do quite what I was after.

After playing around with the other replies here, I made this. It's hacky, but it works!

For this object:

var myObj = {
    pageURL    : "BLAH",
    emailBox   : {model:"emailAddress", selector:"#emailAddress"},
    passwordBox: {model:"password"    , selector:"#password"}
};

... this code:

// Get every value in the object into a separate array item ...
function buildArray(p_MainObj, p_Name) {
    var variableList = [];
    var thisVar = "";
    var thisYes = false;
    for (var key in p_MainObj) {
       thisVar = p_Name + "." + key;
       thisYes = false;
       if (p_MainObj.hasOwnProperty(key)) {
          var obj = p_MainObj[key];
          for (var prop in obj) {
            var myregex = /^[0-9]*$/;
            if (myregex.exec(prop) != prop) {
                thisYes = true;
                variableList.push({item:thisVar + "." + prop,value:obj[prop]});
            }
          }
          if ( ! thisYes )
            variableList.push({item:thisVar,value:obj});
       }
    }
    return variableList;
}

// Get the object items into a simple array ...
var objectItems = buildArray(myObj, "myObj");

// Now use them / test them etc... as you need to!
for (var x=0; x < objectItems.length; ++x) {
    console.log(objectItems[x].item + " = " + objectItems[x].value);
}

... produces this in the console:

myObj.pageURL = BLAH
myObj.emailBox.model = emailAddress
myObj.emailBox.selector = #emailAddress
myObj.passwordBox.model = password
myObj.passwordBox.selector = #password

Solution 19 - Javascript

I think it's worth pointing out that jQuery sorts this out nicely with $.each().

See: .each()

Example:

$('.foo').each(function() {
    console.log($(this));
});

$(this) being the single item inside the object. Swap $('.foo') to a variable if you don't want to use jQuery's selector engine.

Solution 20 - Javascript

var obj = {
    name: "SanD",
    age: "27"
}
Object.keys(obj).forEach((key) => console.log(key,obj[key]));

To loop through the JavaScript Object we can use forEach and to optimize the code we can use the arrow function.

Solution 21 - Javascript

using lodash _.forEach:

_.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
  console.log(key, value);
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

Solution 22 - Javascript

forEach2

(Found here):

var lunch = {
    sandwich: 'ham',
    age: 48,
};
lunch.forEach2(function (item, key) {
    console.log(key);
    console.log(item);
});

Code:

if (!Object.prototype.forEach2) {
    Object.defineProperty(Object.prototype, 'forEach2', {
        value: function (callback, thisArg) {
            if (this == null) {
                throw new TypeError('Not an object');
            }
            thisArg = thisArg || window;
            for (var key in this) {
                if (this.hasOwnProperty(key)) {
                    callback.call(thisArg, this[key], key, this);
                }
            }
        }
    });
}

Solution 23 - Javascript

The solution that works for me is the following:

_private.convertParams = function(params){
    var params = [];
    Object.keys(values).forEach(function(key) {
        params.push({"id":key, "option":"Igual", "value":params[key].id})
    });
    return params;
}

Solution 24 - Javascript

Exotic one - deep traverse

JSON.stringify(validation_messages,(field,value)=>{
  if(!field) return value;

  // ... your code

  return value;
})

In this solution we use replacer which allows to deep traverse the whole object and nested objects - on each level you will get all fields and values. If you need to get the full path to each field, look here.

var validation_messages = {
    "key_1": {
        "your_name": "jimmy",
        "your_msg": "hello world"
    },
    "key_2": {
        "your_name": "billy",
        "your_msg": "foo equals bar",
        "deep": {
          "color": "red",
          "size": "10px"
        }
    }
}

JSON.stringify(validation_messages,(field,value)=>{
  if(!field) return value;

  console.log(`key: ${field.padEnd(11)} - value: ${value}`);

  return value;
})

Solution 25 - Javascript

Using ES8 Object.entries() should be a more compact way to achieve this.

Object.entries(validation_messages).map(([key,object]) => {

    alert(`Looping through key : ${key}`);

    Object.entries(object).map(([token, value]) => {
        alert(`${token} : ${value}`);
    });
});

Solution 26 - Javascript

In 2020 you want immutable and universal functions

This walks through your multidimensional object composed of sub-objects, arrays and string and apply a custom function:

export const iterate = (object, func) => {
  const entries = Object.entries(object).map(([key, value]) =>
    Array.isArray(value)
      ? [key, value.map(e => iterate(e, func))]
      : typeof value === 'object'
      ? [key, iterate(value, func)]
      : [key, func(value)]
  );
  return Object.fromEntries(entries);
};

Usage:

const r = iterate(data, e=>'converted_'+e);
console.log(r);

Solution 27 - Javascript

In my case (on the basis of the preceding) it is possible for any number of levels.

var myObj = {
    rrr: undefined,
    pageURL    : "BLAH",
    emailBox   : {model:"emailAddress", selector:"#emailAddress"},
    passwordBox: {model:"password"    , selector:"#password"},
    proba: {odin:{dva:"rr",trr:"tyuuu"}, od:{ff:5,ppa:{ooo:{lll:'lll'}},tyt:'12345'}}
};


function lookdeep(obj,p_Name,gg){
    var A=[], tem, wrem=[], dd=gg?wrem:A;
    for(var p in obj){
        var y1=gg?'':p_Name, y1=y1 + '.' + p;
        if(obj.hasOwnProperty(p)){
           var tem=obj[p];
           if(tem && typeof tem=='object'){
               a1=arguments.callee(tem,p_Name,true);
               if(a1 && typeof a1=='object'){for(i in a1){dd.push(y1 + a1[i])};}
            }
            else{
               dd.push(y1 + ':' + String(tem));
            }
        }
    };
    return dd
};


var s=lookdeep(myObj,'myObj',false);
for (var x=0; x < s.length; ++x) {
console.log(s[x]+'\n');}

Result:

["myObj.rrr:undefined","myObj.pageURL:BLAH","myObj.emailBox.model:emailAddress","myObj.emailBox.selector:#emailAddress","myObj.passwordBox.model:password","myObj.passwordBox.selector:#password","myObj.proba.odin.dva:rr","myObj.proba.odin.trr:tyuuu","myObj.proba.od.ff:5","myObj.proba.od.ppa.ooo.lll:lll","myObj.proba.od.tyt:12345"]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionedtView Question on Stackoverflow
Solution 1 - JavascriptAgileJonView Answer on Stackoverflow
Solution 2 - JavascriptAxel RauschmayerView Answer on Stackoverflow
Solution 3 - JavascriptRotaretiView Answer on Stackoverflow
Solution 4 - JavascriptChangoView Answer on Stackoverflow
Solution 5 - JavascriptTim SantefordView Answer on Stackoverflow
Solution 6 - JavascriptkennebecView Answer on Stackoverflow
Solution 7 - JavascriptvdegenneView Answer on Stackoverflow
Solution 8 - JavascriptchaosView Answer on Stackoverflow
Solution 9 - JavascriptAzderView Answer on Stackoverflow
Solution 10 - JavascriptWesamView Answer on Stackoverflow
Solution 11 - JavascriptKévin BerthommierView Answer on Stackoverflow
Solution 12 - JavascriptDmitri FarkovView Answer on Stackoverflow
Solution 13 - JavascriptAlirezaView Answer on Stackoverflow
Solution 14 - JavascriptdudeView Answer on Stackoverflow
Solution 15 - JavascriptJepZView Answer on Stackoverflow
Solution 16 - JavascriptChong Lip PhangView Answer on Stackoverflow
Solution 17 - JavascriptSteve WilliamsView Answer on Stackoverflow
Solution 18 - Javascriptuser1833875View Answer on Stackoverflow
Solution 19 - JavascriptDaniel DewhurstView Answer on Stackoverflow
Solution 20 - JavascriptSandip BailkarView Answer on Stackoverflow
Solution 21 - JavascriptdoğukanView Answer on Stackoverflow
Solution 22 - JavascriptT.ToduaView Answer on Stackoverflow
Solution 23 - JavascriptJorge Santos NeillView Answer on Stackoverflow
Solution 24 - JavascriptKamil KiełczewskiView Answer on Stackoverflow
Solution 25 - JavascriptsimmmplyAmitView Answer on Stackoverflow
Solution 26 - JavascriptSebastien HorinView Answer on Stackoverflow
Solution 27 - Javascriptuser2515312View Answer on Stackoverflow