965

Say I create an object thus:

var myObject =
        {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

What is the best way to retrieve a list of the property names? i.e. I would like to end up with some variable 'keys' such that:

keys == ["ircEvent", "method", "regex"]
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
johnstok
  • 96,212
  • 12
  • 54
  • 76
  • 3
    A bit off topic, but if you use underscore.js: `_.keys(myJSONObject)` – Endy Tjahjono Sep 28 '13 at 08:44
  • 5
    **TL;DR:** If you want enumerable properties only: `Object.keys(obj)` Sometimes you want non-enumerable properties as well. Make sure to remember this if you do! To get them, use `Object.getOwnPropertyNames(obj)` https://stackoverflow.com/a/32413145/1599699 – Andrew Jun 17 '20 at 01:12

18 Answers18

1215

In modern browsers (IE9+, FF4+, Chrome5+, Opera12+, Safari5+) you can use the built in Object.keys method:

var keys = Object.keys(myObject);

The above has a full polyfill but a simplified version is:

var getKeys = function(obj){
   var keys = [];
   for(var key in obj){
      keys.push(key);
   }
   return keys;
}

Alternatively replace var getKeys with Object.prototype.keys to allow you to call .keys() on any object. Extending the prototype has some side effects and I wouldn't recommend doing it.

user229044
  • 232,980
  • 40
  • 330
  • 338
slashnick
  • 26,167
  • 10
  • 55
  • 67
  • 19
    I would update again to the effect 'you might be tempted to do this to object prototype ... but don't!' – AnthonyWJones Oct 16 '08 at 12:44
  • 5
    will anybody want to put light on, why is it not recommended to add functions to prototype of Object? – Vishwanath Jan 23 '12 at 10:47
  • 2
    That's a whole different question on it's own, a quick search here on stackoverflow or on google will give you plenty to read – ximi Mar 01 '12 at 19:48
  • I tried this in Google Chrome 27: you can simply use `keys(myJsonObject)` without referencing `Object`. – wecsam Jun 14 '13 at 19:50
  • 4
    The `for (var key in myObject) {...}` technique is useful for javascript runtimes outside of browsers and V8. For example, when passing javascript map-reduce queries into Riak the `Object` object doesn't exist, so the `Object.keys` method isn't available. – awhie29urh2 Jun 20 '13 at 19:46
  • the polyfill is far aways faster. http://jsperf.com/listing-javascript-properties – rdllopes Mar 13 '14 at 13:35
  • `Object.keys()` in ECMA 5.1. In near future it will be available anywhere! – gavenkoa Jul 05 '14 at 18:29
  • 24
    @slashnick Your "simplified version" returns all properties in the object's prototype chain (as it is using a "for ... in"), whereas the (ECMAScript 5.1) `Object.keys` method only returns the object's own properties. I see it as an important distinction. – Martin Carel Oct 16 '14 at 21:57
  • 1
    I agree with @MartinCarel . In my opinion, the answer should be edited to filter out properties using `hasOwnProperty` (since it's a simplified version probably don't need to include the enumeration bug workaround). That's basically what the original question is asking (contextually), and what the actual `Object.keys` function does – user3100783 Oct 19 '14 at 19:10
270

As slashnick pointed out, you can use the "for in" construct to iterate over an object for its attribute names. However you'll be iterating over all attribute names in the object's prototype chain. If you want to iterate only over the object's own attributes, you can make use of the Object#hasOwnProperty() method. Thus having the following.

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        /* useful code here */
    }
}
Community
  • 1
  • 1
Pablo Cabrera
  • 5,749
  • 4
  • 23
  • 28
  • 30
    I wish I had read this before slashnic's answer above. I just had to spend 15 minutes holding down the `esc` key because the object had about a million properties, most of them not used, and I had an alert on it. – Mark Henderson Aug 16 '10 at 06:10
  • 1
    Here's an excelent article on the subject by Zakas himself: http://www.nczonline.net/blog/2010/07/27/determining-if-an-object-property-exists/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+nczonline+(NCZOnline+-+The+Official+Web+Site+of+Nicholas+C.+Zakas) – Pablo Cabrera Aug 19 '10 at 11:17
  • 4
    LOL @MarkHenderson - but next time, just kill the browser's process and restart it instead of wasting 15 minutes :) – JD Smith Sep 06 '12 at 05:53
  • A related function is obj.getOwnPropertyNames() - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames – Steve Goodman Dec 03 '12 at 21:28
  • @MarkHenderson Why won't you use console.log? – LasagnaAndroid Mar 31 '14 at 19:03
  • Beautiful, should've updated the picked answer with this instead of adding a new one though. – LasagnaAndroid Mar 31 '14 at 19:21
104

As Sam Dutton answered, a new method for this very purpose has been introduced in ECMAScript 5th Edition. Object.keys() will do what you want and is supported in Firefox 4, Chrome 6, Safari 5 and IE 9.

You can also very easily implement the method in browsers that don't support it. However, some of the implementations out there aren't fully compatible with Internet Explorer. Here's a more compatible solution:

Object.keys = Object.keys || (function () {
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
        DontEnums = [ 
            'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
            'isPrototypeOf', 'propertyIsEnumerable', 'constructor'
        ],
        DontEnumsLength = DontEnums.length;
        
    return function (o) {
        if (typeof o != "object" && typeof o != "function" || o === null)
            throw new TypeError("Object.keys called on a non-object");
    
        var result = [];
        for (var name in o) {
            if (hasOwnProperty.call(o, name))
                result.push(name);
        }
    
        if (hasDontEnumBug) {
            for (var i = 0; i < DontEnumsLength; i++) {
                if (hasOwnProperty.call(o, DontEnums[i]))
                    result.push(DontEnums[i]);
            }   
        }
    
        return result;
    };
})();

Note that the currently accepted answer doesn't include a check for hasOwnProperty() and will return properties that are inherited through the prototype chain. It also doesn't account for the famous DontEnum bug in Internet Explorer where non-enumerable properties on the prototype chain cause locally declared properties with the same name to inherit their DontEnum attribute.

Implementing Object.keys() will give you a more robust solution.

EDIT: following a recent discussion with kangax, a well-known contributor to Prototype, I implemented the workaround for the DontEnum bug based on code for his Object.forIn() function found here.

jakubde
  • 31
  • 1
  • 2
  • 4
Andy E
  • 338,112
  • 86
  • 474
  • 445
  • Great answer, I think the accepted answer remains the most performant accurate solution, assuming that it is always a JSON dict. This is certainly the one to use elsewhere. – David Snabel-Caunt Oct 26 '10 at 14:00
  • 1
    @David Caunt: Thanks :-) Unfortunately, the accepted answer would still fall foul of the DontEnum bug and you never know what JSON object might have a string like "valueOf" or "constructor" as one of its keys. It will also iterate over extensions to `Object.prototype`. It's often the case, though, that shorter code looks significantly more appealing than larger, more robust code, but the point of this answer is to use ECMAScript 5th's `Object.keys()`, which can be implemented in browsers that don't support it using this code. The native version would be even more performant than this. – Andy E Oct 26 '10 at 14:15
  • Good point - you're right about the bug. I hope any good developer would test for the native methods ahead of using their own implementations. – David Snabel-Caunt Oct 26 '10 at 22:12
  • 2
    Very nice, Andy :) I would just like to remind — no one seems to mention in this thread — that ES5 `Object.keys` only returns an array of strings corresponding to **enumerable** properties of an object. This might not be crucial when working with native (user-defined) objects, but should be very much visible with host objects (although unspecified host objects behavior is a separate — painful — story). To enumerate over ALL (including non-enumerable) properties, ES5 provides `Object.getOwnPropertyNames` (see its support in my compat. table — http://kangax.github.com/es5-compat-table/) – kangax Oct 27 '10 at 02:43
  • 2
    I've integrated this solution into es5-shim http://github.com/kriskowal/es5-shim/blob/master/es5-shim.js#L390 – Kris Kowal Oct 27 '10 at 03:25
  • @Kris: that's great, thanks for crediting :-) @kangax: yes, that's definitely worth mentioning and just reminded me of a piece of code I need to update, thanks :-) – Andy E Oct 27 '10 at 09:11
  • Of course this still only works for `Object`. If you did something silly like putting a shadowing `getFullYear` property on a `Date` instance this would still fail to make that enumerable. To get around that you'd have to have a much longer list of all IE<9 native properties, and check every one with both `hasOwnProperty` and `propertyIsEnumerable`. Not much fun. – bobince Oct 28 '10 at 14:36
  • @bobince: not much fun, indeed! Hopefully, this will tide us over until IE<9 is a distant memory :-) – Andy E Oct 28 '10 at 15:00
  • 2
    Can someone explain why this is implemented as `Object.keys(stuff)` and not `stuff.keys()`? – Blazemonger Sep 16 '11 at 16:29
  • @mblase75: rather than explain it here, you can read a discussion about it from the es-discuss mailing list, starting [here](http://www.mail-archive.com/jsmentors@googlegroups.com/msg01813.html). – Andy E Sep 16 '11 at 17:51
  • @Kiquenet: yes, unfortunately the blog got lost to the ether when I left a previous job that included the hosting... sorry about that! – Andy E Jul 27 '17 at 10:56
  • http://ww1.whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation not found, maybe found in ***archive.org*** ? – Kiquenet Sep 04 '17 at 09:20
41

Note that Object.keys and other ECMAScript 5 methods are supported by Firefox 4, Chrome 6, Safari 5, IE 9 and above.

For example:

var o = {"foo": 1, "bar": 2}; 
alert(Object.keys(o));

ECMAScript 5 compatibility table

Description of new methods

Sam Dutton
  • 14,775
  • 6
  • 54
  • 64
36

Object.getOwnPropertyNames(obj)

This function also shows non-enumerable properties in addition to those shown by Object.keys(obj).

In JS, every property has a few properties, including a boolean enumerable.

In general, non-enumerable properties are more "internalish" and less often used, but it is insightful to look into them sometimes to see what is really going on.

Example:

var o = Object.create({base:0})
Object.defineProperty(o, 'yes', {enumerable: true})
Object.defineProperty(o, 'not', {enumerable: false})

console.log(Object.getOwnPropertyNames(o))
// [ 'yes', 'not' ]

console.log(Object.keys(o))
// [ 'yes' ]

for (var x in o)
    console.log(x)
// yes, base

Also note how:

  • Object.getOwnPropertyNames and Object.keys don't go up the prototype chain to find base
  • for in does

More about the prototype chain here: https://stackoverflow.com/a/23877420/895245

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
17

I'm a huge fan of the dump function.

Ajaxian » JavaScript Variable Dump in Coldfusion

Download the dump function

alt text

Matt
  • 22,224
  • 25
  • 80
  • 116
  • 1
    +1 because I got here in the intention of building something similar (albeit not as good). – Camilo Martin Feb 21 '11 at 06:12
  • 1
    _http://www.netgrow.com.au/assets/files/dump/dump.zip not found_ ***How can I download dump javascript?*** – Kiquenet Jul 26 '17 at 11:14
  • @Kiquenet every time I wanted to build something like this I settle for the regular object inspector, if you want that rendered in HTML there's things like [npm modules](https://www.npmjs.com/package/react-object-inspector). Frankly what got me stuck is I wanted something better than what's on that image but never managed to conceptualize it. It's shitty to browse objects in the inspector but heuristics to try and deduce meaning from arbitrary objects (e.g., sort out arrays of objects into tables with columns) not always works in practice. – Camilo Martin Jul 30 '17 at 15:37
  • 1
    What's about ***Pretty Print Javascript*** _`https://j11y.io/demos/prettyprint/`_ ? – Kiquenet Sep 04 '17 at 09:16
15

Could do it with jQuery as follows:

var objectKeys = $.map(object, function(value, key) {
  return key;
});
sbonami
  • 1,892
  • 17
  • 33
10

This will work in most browsers, even in IE8 , and no libraries of any sort are required. var i is your key.

var myJSONObject =  {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}; 
var keys=[];
for (var i in myJSONObject ) { keys.push(i); }
alert(keys);
Community
  • 1
  • 1
qwerty_jones
  • 101
  • 1
  • 2
10

if you are trying to get the elements only but not the functions then this code can help you

this.getKeys = function() {

    var keys = new Array();
    for(var key in this) {

        if( typeof this[key] !== 'function') {

            keys.push(key);
        }
    }
    return keys;
}

this is part of my implementation of the HashMap and I only want the keys, "this" is the hashmap object that contains the keys

zeacuss
  • 2,563
  • 2
  • 28
  • 32
9

Use Reflect.ownKeys()

var obj = {a: 1, b: 2, c: 3};
Reflect.ownKeys(obj) // ["a", "b", "c"]

Object.keys and Object.getOwnPropertyNames cannot get non-enumerable properties. It's working even for non-enumerable properties.

var obj = {a: 1, b: 2, c: 3};
obj[Symbol()] = 4;
Reflect.ownKeys(obj) // ["a", "b", "c", Symbol()]
sametcodes
  • 583
  • 5
  • 8
8

Under browsers supporting js 1.8:

[i for(i in obj)]
Rix Beck
  • 981
  • 8
  • 5
8

Mozilla has full implementation details on how to do it in a browser where it isn't supported, if that helps:

if (!Object.keys) {
  Object.keys = (function () {
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
        dontEnums = [
          'toString',
          'toLocaleString',
          'valueOf',
          'hasOwnProperty',
          'isPrototypeOf',
          'propertyIsEnumerable',
          'constructor'
        ],
        dontEnumsLength = dontEnums.length;

    return function (obj) {
      if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');

      var result = [];

      for (var prop in obj) {
        if (hasOwnProperty.call(obj, prop)) result.push(prop);
      }

      if (hasDontEnumBug) {
        for (var i=0; i < dontEnumsLength; i++) {
          if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
        }
      }
      return result;
    };
  })();
}

You could include it however you'd like, but possibly in some kind of extensions.js file at the top of your script stack.

Kristofer Sommestad
  • 3,061
  • 27
  • 39
7

With ES6 and later (ECMAScript 2015), you can get all properties like this:

let keys = Object.keys(myObject);

And if you wanna list out all values:

let values = Object.keys(myObject).map(key => myObject[key]);
Anh Hoang
  • 2,242
  • 3
  • 22
  • 23
6

Building on the accepted answer.

If the Object has properties you want to call say .properties() try!

var keys = Object.keys(myJSONObject);

for (var j=0; j < keys.length; j++) {
  Object[keys[j]].properties();
}
Lokesh
  • 3,247
  • 2
  • 33
  • 62
Sydwell
  • 4,954
  • 1
  • 33
  • 36
5

Since I use underscore.js in almost every project, I would use the keys function:

var obj = {name: 'gach', hello: 'world'};
console.log(_.keys(obj));

The output of that will be:

['name', 'hello']
schmijos
  • 8,114
  • 3
  • 50
  • 58
4

A lot of answers here... This is my 2 cents.

I needed something to print out all the JSON attributes, even the ones with sub-objects or arrays (parent name included).

So - For this JSON:

mylittleJson = {
  "one": "blah",
  "two": {
      "twoone": "",
      "twotwo": "",
      "twothree": ['blah', 'blah']
  },
  "three": ""
}

It'd print this:

.one
.two.twoone
.two.twotwo
.two.twothree
.three

Here is function

function listatts(parent, currentJson){
   var attList = []
   if (typeof currentJson !== 'object' || currentJson == undefined || currentJson.length > 0) {
      return
   }
   for(var attributename in currentJson){
       if (Object.prototype.hasOwnProperty.call(currentJson, attributename)) {
           childAtts = listatts(parent + "." + attributename, currentJson[attributename])
           if (childAtts != undefined && childAtts.length > 0)
               attList = [...attList, ...childAtts]
           else 
               attList.push(parent + "." + attributename)
       }
   }
   return attList
}

mylittleJson = {
  "one": "blah",
  "two": {
      "twoone": "",
      "twotwo": "",
      "twothree": ['blah', 'blah']
  },
  "three": ""
}

console.log(listatts("", mylittleJson));

Hope it helps too.

febaisi
  • 644
  • 6
  • 15
4

IE does not support for(i in obj) for native properties. Here is a list of all the props I could find.

It seems stackoverflow does some stupid filtering.

The list is available at the bottom of this google group post:- https://groups.google.com/group/hackvertor/browse_thread/thread/a9ba81ca642a63e0

1

The solution work on my cases and cross-browser:

var getKeys = function(obj) {
    var type = typeof  obj;
    var isObjectType = type === 'function' || type === 'object' || !!obj;

    // 1
    if(isObjectType) {
        return Object.keys(obj);
    }

    // 2
    var keys = [];
    for(var i in obj) {
        if(obj.hasOwnProperty(i)) {
            keys.push(i)
        }
    }
    if(keys.length) {
        return keys;
    }

    // 3 - bug for ie9 <
    var hasEnumbug = !{toString: null}.propertyIsEnumerable('toString');
    if(hasEnumbug) {
        var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
            'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];

        var nonEnumIdx = nonEnumerableProps.length;

        while (nonEnumIdx--) {
            var prop = nonEnumerableProps[nonEnumIdx];
            if (Object.prototype.hasOwnProperty.call(obj, prop)) {
                keys.push(prop);
            }
        }

    }

    return keys;
};
christian Nguyen
  • 1,530
  • 13
  • 11