Iterate through object properties

1,505,813

Solution 1

Iterating over properties requires this additional hasOwnProperty check:

for (var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
        // do stuff
    }
}

It's necessary because an object's prototype contains additional properties for the object which are technically part of the object. These additional properties are inherited from the base object class, but are still properties of obj.

hasOwnProperty simply checks to see if this is a property specific to this class, and not one inherited from the base class.


It's also possible to call hasOwnProperty through the object itself:

if (obj.hasOwnProperty(prop)) {
    // do stuff
}

But this will fail if the object has an unrelated field with the same name:

var obj = { foo: 42, hasOwnProperty: 'lol' };
obj.hasOwnProperty('foo');  // TypeError: hasOwnProperty is not a function

That's why it's safer to call it through Object.prototype instead:

var obj = { foo: 42, hasOwnProperty: 'lol' };
Object.prototype.hasOwnProperty.call(obj, 'foo');  // true

Solution 2

As of JavaScript 1.8.5 you can use Object.keys(obj) to get an Array of properties defined on the object itself (the ones that return true for obj.hasOwnProperty(key)).

Object.keys(obj).forEach(function(key,index) {
    // key: the name of the object key
    // index: the ordinal position of the key within the object 
});

This is better (and more readable) than using a for-in loop.

Its supported on these browsers:

  • Firefox (Gecko): 4 (2.0)
  • Chrome: 5
  • Internet Explorer: 9

See the Mozilla Developer Network Object.keys()'s reference for futher information.

Solution 3

Girls and guys we are in 2019 and we do not have that much time for typing... So lets do this cool new fancy ECMAScript 2016:

Object.keys(obj).forEach(e => console.log(`key=${e}  value=${obj[e]}`));

Solution 4

It's the for...in statement (MDN, ECMAScript spec).

You can read it as "FOR every property IN the obj object, assign each property to the PROPT variable in turn".

Solution 5

In up-to-date implementations of ES, you can use Object.entries:

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

or

Object.entries(obj).forEach(([key, value]) => ...)

If you just want to iterate over the values, then use Object.values:

for (const value of Object.values(obj)) { }

or

Object.values(obj).forEach(value => ...)
Share:
1,505,813
Rafay
Author by

Rafay

Updated on July 16, 2022

Comments

  • Rafay
    Rafay almost 2 years

    var obj = {
        name: "Simon",
        age: "20",
        clothing: {
            style: "simple",
            hipster: false
        }
    }
    
    for(var propt in obj){
        console.log(propt + ': ' + obj[propt]);
    }

    How does the variable propt represent the properties of the object? It's not a built-in method or property. Why does it come up with every property in the object?

    • noob
      noob over 12 years
      if (typeof(obj[propt]) === 'object') {/* Do it again */ }
    • Rafay
      Rafay over 12 years
      Well, really sorry for this question. I know what a loop is, I couldn't get my head around "looping through object properties", which I think is cleared now. Also, they have recommended me "JavaScript Step by Step 2nd Edition - Steve Suehring at school.
    • Nathan C. Tresch
      Nathan C. Tresch over 11 years
      This is a fine begginers question. I'd add that I have 15 years of professional experience with other languages and I needed this answer. I'd plus 2000 if I could.
    • Nathan C. Tresch
      Nathan C. Tresch over 11 years
      @ItayMoav-Malimovka From parsing the language in the question, as a linguist it's clear that sees that it's looping, he wants to know that the IN operator passes the object properties as "propt".
    • Георги Кременлиев
      Георги Кременлиев almost 11 years
    • Dave
      Dave almost 9 years
      Crazy, but I've been coming to this page every few months for years to relearn the syntax on how to do this. I don't bother to remember how to do this... I just remember that this page is always here on SO.
    • Michael Cole
      Michael Cole over 7 years
      this answer shows two alternatives using underscore and lodash. Helpful if they are already available to you: stackoverflow.com/a/19023387/1483977
    • Admin
      Admin about 7 years
      This is the strangest page I've seen on StackOverflow. If you read the question carefully, only one answer even begins to attempt to answer what is actually being asked, and it has a score of -6. The highest scoring answer, which was accepted, not only doesn't answer, but is simply wrong.
  • Qqwy
    Qqwy over 12 years
    ! with the important difference that these 'lists of properties' can have names as keys, while normal JS arrays can only have numbers as keys.
  • Rafay
    Rafay over 12 years
    Thanks a lot, I understand it now. I was banging my head, going through books and Google.
  • Christian C. Salvadó
    Christian C. Salvadó over 12 years
    Agree with @RightSaidFred, the in operator and the for statement are not involved at all, the for-in statement represents a grammar production on its own: for ( LeftHandSideExpression in Expression ), for ( var VariableDeclarationNoIn in Expression )
  • davidmdem
    davidmdem almost 11 years
    @B T According to the Mozilla documentation: "If you only want to consider properties attached to the object itself, and not its prototypes, use getOwnPropertyNames or perform a hasOwnProperty check (propertyIsEnumerable can also be used)."
  • Doug Molineux
    Doug Molineux over 10 years
    Odd this answer has so many up votes, especially since these popular comments seem to contradict it.
  • Danation
    Danation over 10 years
    @PaulCarroll, that is incorrect. for each is different. This is what you're looking for: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • computrius
    computrius over 10 years
    Why is this marked as the answer? It is quite possibly the least helpful one in this thread..
  • Dom Vinyard
    Dom Vinyard over 10 years
  • Dan Dascalescu
    Dan Dascalescu about 10 years
    @PeteHerbertPenito, odd that nobody bothered to edit the answer until I did.
  • Alex S
    Alex S about 10 years
    What exactly is the point of calling object.hasOwnProperty()? Doesn't the fact that property has whatever value imply that its in object?
  • Kyle Richter
    Kyle Richter about 10 years
    Because, Alex S, an object's prototype contains additional properties for the object which are technically part of the object. They are inherited from the base object class, but they are still properties. hasOwnProperty simply checks to see if this is a property specific to this class, and not one inherited from the base class. A good explanation: brianflove.com/2013/09/05/javascripts-hasownproperty-method
  • Kyle Richter
    Kyle Richter about 10 years
    I feel that I should mention, however, that Object.keys(obj) is now a much better solution for getting the keys of the object itself. Link to the Mozilla documentation: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • KyleMit
    KyleMit about 10 years
    And if you need support for old browsers, you can use this polyfill
  • Adria
    Adria over 9 years
    If you like performance, you won't use hasOwnProperty. You'll add non-enumerable properties the proper way using Object.defineProperty
  • Alexyu
    Alexyu over 9 years
    In environments that support this language construct, this method allows Array.foreach to be called: Object.keys(myObject).forEach(function(key,index) { //key = the name of the object key //index = the ordinal position of the key within the object });
  • Victor Grazi
    Victor Grazi over 9 years
    Tried this in MSIE 9.0 but it doesn't recognize Object.keys()
  • Admin
    Admin over 8 years
    if('javascript'.hasOwnProperty(0)) console.log('Well, you've really just screwed me over, didn't you, javascript?');
  • Jadiel de Armas
    Jadiel de Armas over 8 years
    Please look at the example of @Will just above me. This answer is not correct. If your object is a string, the solution given by this answer will not work. Just try the following: for (var property in 'javascript') console.log(property)
  • Admin
    Admin over 8 years
    @JadieldeArmas strings are just a corner case you have to watch out for. Like everything else in javascript :/
  • Jadiel de Armas
    Jadiel de Armas over 8 years
    I think that the confusion is mainly introduced here because a Javascript object and a JSON object are not the same thing.
  • Ondrej Svejdar
    Ondrej Svejdar about 8 years
    @faiz - see my comments, it is safeguard against being stuck in endless loop when you recurrently walk trough object that has cyclic references
  • Ruan Mendes
    Ruan Mendes about 8 years
    @Rafay I really don't understand how this answer has anything to do with the actual question. The loop does not show any inherited properties unless the OP has modified Object.prototype. This may be good advice but you yourself said I couldn't get my head around "looping through object properties". Many chose not to add a hasOwnProperty check. If you created the object yourself and you haven't added some dumb library that adds properties to Object.Prototype there's no need for such check.
  • Victor Zakharov
    Victor Zakharov almost 8 years
    One important piece of information is missing. property is a string here, should have been called propertyName. Otherwise can cause confusion for JS newbies like myself, i.e. what to do inside the if.
  • Admin
    Admin over 7 years
    This answer needs to be updated for "ES7", with methods such as Object.entries and Object.values.
  • Beejor
    Beejor over 7 years
    Tiny polyfill for IE 9 and below: if( !Object.keys ){ Object.keys = function( o ){ var p, k = []; for( p in o ){ if( Object.prototype.hasOwnProperty.call( o, p ) ){ k.push( p ); } return k; }; }
  • Bumpy
    Bumpy over 7 years
    Least helpful answer? Depends what you think the OP was asking; when I first read the question it seemed like baffled bemusement about the mechanism by which a variable can be used to inspect an object's properties, and which this answer explains eloquently (the 'for-in' misnomer notwithstanding). The question "Why does it come up with every property" I see could imply the OP was looking for hasOwnProperty but doesn't know it, but I think it's more likely this was what the OP wanted to know, and has incorrectly accepted a correct answer to a different question. :-)
  • Megajin
    Megajin over 7 years
    Thanks, this helped me. I needed a solution to determine the end of the loop, which was impossible with for-in. Now that I can check against the array of keys it is easy. Thanks again!
  • JounceCracklePop
    JounceCracklePop over 7 years
    If you don't need to support IE8 and you're only using well-behaved libraries that don't define enumerable properties on Object.prototype, there is no longer a reason to use hasOwnProperty when looping through properties. Now that I have control over whether I want a property to be enumerable, respect my choices, and don't disallow me from using inheritance for no good reason.
  • krillgar
    krillgar over 7 years
    How is this any different than Danny R's answer?
  • Frank Roth
    Frank Roth over 7 years
    It is a oneliner and uses map instead of forEach. And also the console.log satement is maybe interesting for some people.
  • AJ_83
    AJ_83 over 7 years
    Good solution. But how to break the iteration?!
  • Benj
    Benj over 7 years
    Interesting way to do that. Thanks for the function* discovery!
  • Michaelangel007
    Michaelangel007 over 7 years
    Satly, that doesn't work when obj=window.performance.memory :-/ Where as for in does. i.e. var obj = window.performance.memory; for( key in obj ) console.log( 'key=' + key + ' val=' + obj[key] );
  • Frank Roth
    Frank Roth over 7 years
    window.performance.memory is only supported by chrome and Object.keys(obj) returns an empty array. This has nothing to do with .map.
  • Daniel Z.
    Daniel Z. about 7 years
    @AJ_83 There's no good way to break out of a forEach(). Use some() in this case, and return true to break
  • Admin
    Admin about 7 years
    This answer is completely unrelated to the question, and is in fact very misleading. Fine if one wants to use .hasOwnProperty(), but it falls under the same category of "what if something corrupts my environment", which begs the question... what if .hasOwnProperty itself was corrupted. Much of the time a good developer can ensure the environment is clean, making this totally unnecessary.
  • kayleeFrye_onDeck
    kayleeFrye_onDeck about 7 years
    In case anyone doesn't want to monkey around re-structuring this single-liner to do more than one thing at a time with e, I've posted this gist. It's basically just like most hash implementations, and uses ( (key) => (value) ) instead of { key => value }, but if you haven't had to deal with that before, it could help you visualize it better: gist.github.com/the-nose-knows/9f06e745a56ff20519707433e28a4‌​fa8
  • Umut Çağdaş Coşkun
    Umut Çağdaş Coşkun about 7 years
    Thank you. I guess it's more clear than accepted answer.
  • developerbmw
    developerbmw over 6 years
    this doesn't answer the question at all. why 1700 people upvote it?
  • developerbmw
    developerbmw over 6 years
    Why on earth does this "answer" have 10 upvotes? It completely fails to answer the question. I'm beginning to lose faith in the intelligence on the average JS developer.
  • Frank Roth
    Frank Roth over 6 years
  • viktarpunko
    viktarpunko over 6 years
    @developerbmw I understand that using ES6 features is more right way, but I've answered a year ago. Please, share your thoughts with us when you have a minute.
  • Mario
    Mario over 6 years
    this would be the best solution (object.entries...), but I can't use it. When you want to do this multiple times and can't support it in your framework, you can use the polyfill on this page: developer.mozilla.org/nl/docs/Web/JavaScript/Reference/…
  • Yay295
    Yay295 over 6 years
    You can trim two more characters from Grant's proposal by removing the parentheses for log: Object.keys(obj).map(e => console.log`key=${e} value=${obj[e]}`).
  • Meghan
    Meghan about 6 years
    These are the same values returned from Object.keys(obj)
  • Bob Stein
    Bob Stein about 6 years
    $.each({foo:1, length:0, bar:2}, function(k,v){console.log(k,v)}) $.each is not suitable for objects. If an object happens to have a length property and its value happens to be zero, the whole object is treated as if it were an empty array.
  • Bob Stein
    Bob Stein about 6 years
    Details why I think this is a bug-inviting approach.
  • gnzg
    gnzg about 6 years
    The third suggestion is great if you only the properties' values. Awesome!
  • Katharine Osborne
    Katharine Osborne about 6 years
    Upvoting this, given it's simplicity. In my use case I need to check all the attributes in an object for dodgy values-NaNs, nulls, undefined (they were points on a graph and these values prevented the graph from drawing). To get the value instead of the name, in the loop you would just do obj[someVariable]. Perhaps the reason it was downvoted so much is because it is not recursive. So this would not be an adequate solution if you have a highly structured object.
  • Admin
    Admin almost 6 years
    The idea is to focus more on native methods, instead of suggesting the user add a 10000 line library to their page. Don't get me wrong, I do like using Lodash but there's a time and a place for it and it isn't this.
  • Jona
    Jona almost 6 years
    why is this more readable than for-in? for candidate in candidateStatus... seems readable to me
  • David Callanan
    David Callanan over 5 years
    This is the first answer I've found that actually answers the question.
  • Danny
    Danny over 5 years
    As mentioned in other comments, forEach is more appropriate here, as map is intended to return a new array with the results of calling the code block on each iteration. But we are only interested in the side affects of each iteration, not the return value, hence we don't need that new array that map gives us.
  • Tom Russell
    Tom Russell over 5 years
    "For each property in the object". One of my pet peeves is messing up plurality. It's so confusing to beginners.
  • Luke
    Luke over 5 years
    Putting variables as separate arguments for console.log will often display more information (color formatting, the ability to expand objects, etc.), so this is better IMO: Object.keys(obj).forEach(e => console.log('key=', e, 'value=', obj[e]));
  • Ian Steffy
    Ian Steffy over 5 years
    This answer does not iterate through the list of objects, rather they key names of each object and the return value is a string.
  • alostr
    alostr about 5 years
    notice that using Object.keys changes the order of the keys, and sorts them, so if you care about the order of items in the object, you should use the accepted answer
  • Duncan
    Duncan almost 5 years
    It surprises me that anyone would find this syntax "more readable". I guess it all depends what your background is, but for me it's hard to beat the for(loop control here) { do stuff here } syntax. That structure has been around in various languages since before most people on StackExchange were born. The javascript structure, with a function call as an argument, is rather new, in the grand scheme of things.
  • Michiel
    Michiel almost 5 years
    Although you are not actually answering the OP's question, this was very helpful for me, I did not know about Reflect yet.
  • bvdb
    bvdb almost 5 years
    @KatharineOsborne or perhaps it is because the following phrase is a bit cryptic: "Therefore if you use block {}, you can iterate." The code says more than the text.
  • ToolmakerSteve
    ToolmakerSteve over 4 years
    @IanS - sounds like you are looking for "how to iterate through the items in an array". This Q&A is about "how to iterate through the properties of an Object". In JavaScript, unlike some other languages, two different syntaxes are required for these cases. For array items, use for .. of, not for .. in.
  • Nicolas
    Nicolas over 4 years
    Hi, could you add more information about your answer, providing only code does not help.
  • Fouad Boukredine
    Fouad Boukredine over 4 years
    Hi @Nicolas I've added a line by line explanation to the code. Let me know if it's still not clear
  • Darkproduct
    Darkproduct over 4 years
    Because forEach skips empty values, I think you could get rid of the if and just do Object.keys(obj).forEach(e => console.log(`key=${e} value=${obj[e]}`)); like Frank Roth's answer.
  • Jonathan
    Jonathan over 4 years
    Should be Object with uppercase o though, no?
  • Antony Hatchkins
    Antony Hatchkins almost 4 years
    shouldBeBar is undefined for all three iterations.
  • dylanh724
    dylanh724 almost 4 years
    undefined is impossible since it's, well, clearly defined in front of you :) This deducts to 2 possibilities: (1) Are you checking for shouldBeBar OUTSIDE of the if() block? Then yes, it will be undefined (out of scope). Or (2) Did you typo the var name?
  • Brian Burns
    Brian Burns over 3 years
    @user9016207 this answer is from 2016, and was more applicable then - esp if you were already using lodash. nowadays if you need individual fns from lodash you can get them one at a time, eg npmjs.com/package/lodash.keys
  • Dmitry
    Dmitry over 3 years
    Nice one, you can even use methods, if properties are objects too!
  • corsiKa
    corsiKa over 3 years
    @Duncan Because of the atrocious "hasOwnProperty" malarkey.
  • shrekuu
    shrekuu over 3 years
    @Jonathan Note it is the object variable in the first line.
  • Cyril N.
    Cyril N. over 3 years
    I have updated the code to avoid confusion ;)
  • Burak
    Burak about 3 years
    The link is broken :(.
  • Matt Ball
    Matt Ball about 3 years
    @Burak thanks for letting me know - fixed. In the future, feel free to suggest an edit :)
  • OzzyCzech
    OzzyCzech almost 3 years
    this is best answer, you should use for (const [key, value] of Object.entries(obj)) { }
  • Ernesto Alfonso
    Ernesto Alfonso over 2 years
    You are iterating over the same object two times, this is not a correct way to do this. Please update this answer merging all in one forEach, because this is a propagation of bad practices.