1678

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"
    }
}
Paresh Mangukiya
  • 14,668
  • 7
  • 90
  • 90
edt
  • 20,403
  • 27
  • 78
  • 114
  • 11
    possible duplicate of [Loop through JavaScript object](http://stackoverflow.com/questions/684672/loop-through-javascript-object) – BuZZ-dEE Apr 23 '14 at 12:04

25 Answers25

2177
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]);
    }
}
Darryl Hein
  • 134,677
  • 87
  • 206
  • 257
AgileJon
  • 51,100
  • 4
  • 38
  • 38
  • 14
    Internet Explorer does not agree (*sigh*), says "Object does not support this property or method" when you do obj[prop]. I have yet to find a solution to this. – user999717 Dec 21 '11 at 12:02
  • 2
    @MildFuzz actually it makes sense if you consider that JS objects do not necessary have numerical keys. You can't just iterate through an object. JS's `for in` is very similar to a traditional `foreach`. – Jake Wilson Feb 28 '13 at 05:16
  • 5
    for...in is a good solution, but if you use promises in the for()-loop be careful, because if you create a var in the loop, you can't use it in the promise' then-function. You var in the loop exists only one time, so it has in every then-function the same, even the last value. If you have that problem, try "Object.keys(obj).forEach" or my answer below. – Biber Nov 22 '16 at 21:15
  • hasOwnProperty is almost always redundant for modern browsers (IE9 +). – Filyus Jun 05 '20 at 10:14
824

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]);

});
beaver
  • 16,227
  • 2
  • 31
  • 57
Axel Rauschmayer
  • 22,683
  • 4
  • 21
  • 15
  • 37
    +1 for brevity of code but apparently, doesn't perform as efficient as a for surprisingly. [JSPerf - for in vs Object.keys](http://jsperf.com/objdir) – techiev2 Sep 04 '12 at 12:33
  • 6
    Beware of this error using this approach: "TypeError: Object.keys called on non-object". The `for ... in ... hasOwnProperty` pattern can be called on anything, as far as I can tell (object, array, null, undefined, true, false, number primitive, objects). – theazureshadow Oct 12 '12 at 02:17
  • 2
    Note that IE7 doesn't support this. – Paul D. Waite Nov 08 '13 at 11:02
  • 3
    @techiev2 those tests were never valid. See my updated ones for the current state of performance: http://jsperf.com/objdir/20 – OrganicPanda Oct 16 '14 at 10:39
  • 4
    @techiev2: it's not `Object.keys()` which makes it slow, it's rather the `forEach()` and the repeated access to `.length`! If you use a classic `for`-loop instead, it's almost twice as fast as `for..in` + `hasOwnProperty()` in Firefox 33. – CodeManX Nov 05 '14 at 23:50
  • Does keys(obj) return property keys of the child objects too? to what depth? does it avoid possible loop references? – Saba Ahang Oct 15 '15 at 06:39
  • @SabaAhang No. The purpose of [Object.keys](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) is to get only the direct (vs inherited) keys of an object, as an array. This excludes keys set on the object's prototypes that it inherits. In other words, it only includes keys where [hasOwnProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) is true. – Ben J Mar 09 '16 at 06:07
  • 1
    Object.keys(obj).reduce((p,c)=> p.concat(obj[c]),[]) – CpILL Jun 09 '16 at 20:15
  • 1
    seems like [this is now the only jslint recommended `for` loop](http://stackoverflow.com/a/30518734/274502). from the site's help: _" JSLint does not recommend use of the `for` statement. Use array methods like `forEach` instead. JSLint does not recommend use of the `for in` statement. Use `Object.keys` instead."_ – cregox Feb 21 '17 at 12:05
  • 2
    @techiev2 that is not surprising at all, Axel Rauschmayer's method is using `keys` function and `forEach` function and it needs to parse the anonymous function and then it calls the anonymous function on each element of the forEach loop. If you know about programming you will understand all this parsing and function calls is taking much more time than a native solution like the for structure loop. – vdegenne Sep 23 '17 at 12:03
  • 1
    If you are in react, you probably want to use `.map()` instead of `.forEach()` https://stackoverflow.com/questions/39965579/how-to-loop-an-object-in-react – Andreas Riedmüller Aug 01 '18 at 13:11
  • A more functional and encapsulated alternative is `const mapr = o => Object.keys(o).map(key => o[key])` then `mapr(obj)` – garajo Dec 30 '18 at 06:23
387

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]);
         }
      }
   }
}
Himanshu Jansari
  • 28,446
  • 26
  • 101
  • 128
Chango
  • 6,464
  • 1
  • 25
  • 37
  • 46
    In short: check [`hasOwnProperty`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) inside your `for`-`in` loops. – Rory O'Kane Nov 21 '12 at 05:11
  • 61
    Note that this is only necessary if your object HAS prototype methods. For example, if the object you're looping through is just a JSON object, you won't need this check. – gitaarik Dec 29 '13 at 19:46
  • 6
    @rednaw To be safe I use that check because Object.prototype can be modified. No sane script would do that, but you cannot control what scripts might be run in your page by insane browser extensions. Browser extensions run in your page (on most browsers) and they can cause odd problems (e.g. set window.setTimeout to null!). – robocat Dec 05 '14 at 02:42
383

In ES6/2015 you can loop through an object like this: (using 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.
});

jsbin

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

jsbin

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.

Rotareti
  • 31,464
  • 14
  • 87
  • 93
  • 2
    for your ES7 using Object.entries example, you need to wrap the arrow function parameters [key,val] in parentheses like: `Object.entries(myObj).forEach(([key, val]) => { /* statements*/ } – puiu Mar 02 '17 at 17:10
  • 8
    I think it would be useful to add the fact that Object.entries and Object.keys does not iterate over the prototype which is the big difference between it and the for in construct. – steviesh Mar 28 '17 at 19:06
97

Using Underscore.js’s _.each:

_.each(validation_messages, function(value, key){
    _.each(value, function(value, key){
        console.log(value);
    });
});
Leo
  • 7,914
  • 2
  • 35
  • 46
Tim Santeford
  • 24,045
  • 13
  • 70
  • 98
57

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
}

*/
kennebec
  • 94,076
  • 30
  • 99
  • 125
51

This answer is an aggregate of the solutions that were provided in this post with some performance feedbacks. I think there is 2 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 cautious, 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 app 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 values,

✔ 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 (1st and last tests).

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

vdegenne
  • 8,291
  • 10
  • 65
  • 90
31

I know it's waaay late, but it did take me 2 minutes to write this 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]);
            }

        }

    }

}
Azder
  • 4,408
  • 6
  • 34
  • 56
  • 1
    Why are you storing `hasOwnProperty` in `owns` and then calling `owns.call(obj, prop)` instead of just calling `obj.hasOwnProperty(prop)` as [this answer](http://stackoverflow.com/a/2869372/578288) does? – Rory O'Kane Nov 21 '12 at 05:25
  • 14
    Because `obj` might have the `hasOwnProperty` function defined on it self so it will not use the one from `Object.prototype`. You can try before the `for` loop like this `obj.hasOwnProperty = function(){return false;}` and it will not iterate over any property. – Azder Nov 21 '12 at 05:38
  • 4
    @Azder +1 for the answer and +1 if I could for the nice thing about Object.prototype.hasOwnProperty. I saw that previously inside the source code of the underscore library but don't know why. – Samuel Jan 03 '14 at 15:28
30
for(var k in validation_messages) {
    var o = validation_messages[k];
    do_something_with(o.your_name);
    do_something_else_with(o.your_msg);
}
chaos
  • 115,791
  • 31
  • 292
  • 308
14

p is the value

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

OR

Object.keys(p).forEach(key => { console.log(key, p[key]) })
Wesam
  • 848
  • 3
  • 15
  • 27
10

In ES7 you can do:

for (const [key, value] of Object.entries(obj)) {
  //
}
8
for(var key in validation_messages){
    for(var subkey in validation_messages[key]){
        //code here
        //subkey being value, key being 'yourname' / 'yourmsg'
    }
}
Dmitri Farkov
  • 7,997
  • 1
  • 27
  • 44
7

Few ways to do that...

1) 2 layers 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);
Alireza
  • 83,698
  • 19
  • 241
  • 152
6

Another option:

var testObj = {test: true, test1: false};
for(let x of Object.keys(testObj)){
    console.log(x);
}
dude
  • 4,522
  • 9
  • 44
  • 77
  • I tried your solution in Chrome 55.0 and you get a type error. Your answer looks nice and succinct, if you can get it working it would probably be one of the better options. I tried to figgure it out but don't understand your solution. – TolMera Dec 23 '16 at 13:38
  • 2
    @TolMera Fixed. – dude Dec 23 '16 at 14:05
5

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.

JepZ
  • 933
  • 12
  • 24
4

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
vdegenne
  • 8,291
  • 10
  • 65
  • 90
Chong Lip Phang
  • 6,658
  • 5
  • 49
  • 71
3

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.

Arya
  • 2,140
  • 1
  • 9
  • 27
Daniel Dewhurst
  • 2,298
  • 1
  • 17
  • 35
3

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

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

2

I couldn't get the above posts 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
CrazyMatt
  • 401
  • 3
  • 12
0

The solution that work 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;
}
Jorge Santos Neill
  • 1,089
  • 7
  • 6
0

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 whole object and nested objects - on each level you will get all fields and values. If you need to get 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;
})
Community
  • 1
  • 1
Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
0

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}`);
    });
});
simmmplyAmit
  • 129
  • 1
  • 3
0

in 2020 you want immutable and universal functions

This walk 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);
Sebastien Horin
  • 8,814
  • 4
  • 39
  • 51
0

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);
                }
            }
        }
    });
}
T.Todua
  • 44,747
  • 17
  • 195
  • 185
-7

In my case (on the basis of the preceding) is possible 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"]