517

I would like to get the keys of a JavaScript object as an array, either in jQuery or pure JavaScript.

Is there a less verbose way than this?

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
    keys.push(key);
}
3
  • 5
    Besides from adding if(foo.hasOwnProperty(key)), that's what I'd do. Or, use $.map. Commented Jan 6, 2012 at 19:17
  • 12
    Oh for a Pythonic one-liner, though... Commented Jan 6, 2012 at 19:17
  • @unsynchronized Please never post solutions as comments. Your comment intentionally breaches the clear and intentional page structure design. Commented Jul 8, 2020 at 3:44

8 Answers 8

812

Use Object.keys:

var foo = {
  'alpha': 'puffin',
  'beta': 'beagle'
};

var keys = Object.keys(foo);
console.log(keys) // ['alpha', 'beta'] 
// (or maybe some other order, keys are unordered).

This is an ES5 feature. This means it works in all modern browsers but will not work in legacy browsers.

The ES5-shim has a implementation of Object.keys you can steal

Sign up to request clarification or add additional context in comments.

5 Comments

And what about mobile browsers ?
@SmartyTwiti: I'm not sure. I'd assume it does in like Chrome or Firefox.
MDN also has the above referred Polyfill, but notes bugs in IE7 and maybe 8, then refers off to a much shorter Polyfill here: tokenposts.blogspot.com.au/2012/04/…
So how did one do this before ES5?
the amount of times I tried to call keys as a property of an instance before it dawned on me it's a static class method... comprehension of api--
62

You can use jQuery's $.map.

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' },
keys = $.map(foo, function(v, i){
  return i;
});

1 Comment

Or each, if you're doing something with them. $.each(foo, function(index, value){/* do something with index */});
40

Of course, Object.keys() is the best way to get an Object's keys. If it's not available in your environment, it can be trivially shimmed using code such as in your example (except you'd need to take into account your loop will iterate over all properties up the prototype chain, unlike Object.keys()'s behaviour).

However, your example code...

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
    keys.push(key);
}

jsFiddle.

...could be modified. You can do the assignment right in the variable part.

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [], i = 0;
for (keys[i++] in foo) {}

jsFiddle.

Of course, this behaviour is different to what Object.keys() actually does (jsFiddle). You could simply use the shim on the MDN documentation.

10 Comments

I liked this var keys = [], i = 0; for (keys[i++] in foo) {} +1
I heard that "for in" doesn't guarantee order, do you know if Object.keys does?
@ChrisStephens Neither guarantee order, even if the keys end up being in an ordered array.
all of these solutions need a hasOwnProperty() check, surely?
@TIMINeutron There's no reason why it shouldn't :)
|
18

In case you're here looking for something to list the keys of an n-depth nested object as a flat array:

const getObjectKeys = (obj, prefix = '') => {
  return Object.entries(obj).reduce((collector, [key, val]) => {
    const newKeys = [ ...collector, prefix ? `${prefix}.${key}` : key ]
    if (Object.prototype.toString.call(val) === '[object Object]') {
      const newPrefix = prefix ? `${prefix}.${key}` : key
      const otherKeys = getObjectKeys(val, newPrefix)
      return [ ...newKeys, ...otherKeys ]
    }
    return newKeys
  }, [])
}

console.log(getObjectKeys({a: 1, b: 2, c: { d: 3, e: { f: 4 }}}))

Comments

8

I don't know about less verbose but I was inspired to coerce the following onto one line by the one-liner request, don't know how Pythonic it is though ;)

var keys = (function(o){var ks=[]; for(var k in o) ks.push(k); return ks})(foo);

3 Comments

Maybe that should be var enumerableKeysOnThePrototypeChain ;)
Maybe we're smart enough to know we don't have to worry about hasOwnProperty if the object is created entirely under our purview as opposed to being imported from somewhere else
not as pythonic as @alex's 2nd answer (for (keys[i++] in foo) {}) though, because you're still performing Array.push() (not to mention declaring a whole function). A pythonic implementation should rely as much on implicit comprehension as possible, and failing that, using a lambda expression.
5

Summary

For getting all of the keys of an Object you can use Object.keys(). Object.keys() takes an object as an argument and returns an array of all the keys.

Example:

const object = {
  a: 'string1',
  b: 42,
  c: 34
};

const keys = Object.keys(object)

console.log(keys);

console.log(keys.length) // we can easily access the total amount of properties the object has

In the above example we store an array of keys in the keys const. We then can easily access the amount of properties on the object by checking the length of the keys array.

Getting the values with: Object.values()

The complementary function of Object.keys() is Object.values(). This function takes an object as an argument and returns an array of values. For example:

const object = {
  a: 'random',
  b: 22,
  c: true
};


console.log(Object.values(object));

Comments

2

Year 2022 and JavaScript still does not have a sound way to work with hashes?

This issues a warning but works:

Object.prototype.keys = function() { return Object.keys(this) }
console.log("Keys of an object: ", { a:1, b:2 }.keys() )

// Keys of an object:  Array [ "a", "b" ]
// WARN: Line 8:1:  Object prototype is read only, properties should not be added  no-extend-native

That said, Extending Built-in Objects is Controversial.

Comments

0

If you decide to use Underscore.js you better do

var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
_.each( foo, function( val, key ) {
    keys.push(key);
});
console.log(keys);

1 Comment

Why? What is the explanation?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.