269

I have an associative array in JavaScript:

var dictionary = {
    "cats": [1,2,3,4,5],
    "dogs": [6,7,8,9,10]
};

How do I get this dictionary's keys? I.e., I want

var keys = ["cats", "dogs"];

Just to get the terminology correct - there is no such thing as an 'associative array' in JavaScript - this is technically just an object and it is the object keys we want.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689

6 Answers6

383

Try this:

var keys = [];
for (var key in dictionary) {
  if (dictionary.hasOwnProperty(key)) {
    keys.push(key);
  }
}

hasOwnProperty is needed because it's possible to insert keys into the prototype object of dictionary. But you typically don't want those keys included in your list.

For example, if you do this:

Object.prototype.c = 3;
var dictionary = {a: 1, b: 2};

and then do a for...in loop over dictionary, you'll get a and b, but you'll also get c.

JW.
  • 50,691
  • 36
  • 115
  • 143
  • No need to declare "var keys = []", unless you need to use it after the loop. – mzalazar Sep 03 '14 at 16:25
  • 2
    @mzalazar, you better do or it'll be a global variable, which is bad practice. – b00t Mar 09 '16 at 07:42
  • @b00t i though that by declaring a variable inside a for loop... it wouln't be set in global space... now you made me doubt hehe :) – mzalazar Mar 09 '16 at 13:38
  • 2
    @mzalazar, but you're not declaring it (**keys**) at any point if you're just using `keys.push(key);`. You're just pulling (and thus declaring it) from the global namespace. :) – b00t Mar 11 '16 at 11:58
184
for (var key in dictionary) {
  // Do something with key
}

It's the for..in statement.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wombleton
  • 8,336
  • 1
  • 28
  • 30
  • 1
    Just noticed that there should be a colon instead of a comma between "dogs" and the array above. Assume it's due to transcription. – wombleton Feb 18 '09 at 00:08
  • 68
    Very important to check for `dictionary.hasOwnProperty(key)` otherwise you may end up with methods from the prototype chain.. – Tigraine Jun 09 '11 at 06:16
  • 4
    From the same article: _Iterates over the enumerable properties of an object, in arbitrary order_. If key order is important, you need to do something like pushing them in an array, sorting it, and then using a for() loop to get keys from the sorted array with which to index the original object. – mcmlxxxvi Jul 26 '13 at 21:31
  • 1
    It is, of course, fair to optimize by omitting the dictionary.hasOwnProperty check if you can be confident that the object lacks a prototype. But it's important to be aware of the possibility of prototype inheritance in this context, since JavaScript dictionaries are really objects. – fixermark Aug 05 '15 at 15:08
103

You can use: Object.keys(obj)

Example:

var dictionary = {
  "cats": [1, 2, 37, 38, 40, 32, 33, 35, 39, 36],
  "dogs": [4, 5, 6, 3, 2]
};

// Get the keys
var keys = Object.keys(dictionary);

console.log(keys);

See reference below for browser support. It is supported in Firefox 4.20, Chrome 5, and Internet Explorer 9. Object.keys() contains a code snippet that you can add if Object.keys() is not supported in your browser.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rob de la Cruz
  • 1,182
  • 1
  • 8
  • 4
  • I'm switching this to the accepted answer now. Only IE8 doesn't support it anymore (for which a polyfill is available https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) – Simon_Weaver Dec 11 '17 at 01:55
16

Just a quick note. Be wary of using for..in if you use a library (jQuery, Prototype, etc.), as most of them add methods to created Objects (including dictionaries).

This will mean that when you loop over them, method names will appear as keys. If you are using a library, look at the documentation and look for an enumerable section, where you will find the right methods for iteration of your objects.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jesse
  • 10,370
  • 10
  • 62
  • 81
3

Simple jQuery way:

This is what I use:

DictionaryObj being the JavaScript dictionary object you want to go through. And value, key of course being the names of them in the dictionary.

$.each(DictionaryObj, function (key, value) {
    $("#storeDuplicationList")
        .append($("<li></li>")
        .attr("value", key)
        .text(value));
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Exzile
  • 389
  • 4
  • 15
  • 1
    this requires jQuery (which is fine) but you forgot to mention it :-) – Simon_Weaver Mar 25 '15 at 17:04
  • @Exzile The argument names in your function definition are very confusing. It says at https://api.jquery.com/jquery.each/ that the callback is Function( String propertyName, Object valueOfProperty ). Your names imply the reverse. – Chris May 01 '15 at 10:25
  • @Chris I will update that for you. Thanks for pointing that out. – Exzile May 01 '15 at 13:52
0

I am currently using Rob de la Cruz's reply:

Object.keys(obj)

And in a file loaded early on I have some lines of code borrowed from elsewhere on the Internet which cover the case of old versions of script interpreters that do not have Object.keys built in.

if (!Object.keys) {
    Object.keys = function(object) {
        var keys = [];
        for (var o in object) {
            if (object.hasOwnProperty(o)) {
                keys.push(o);
            }
        }
        return keys;
    };
}

I think this is the best of both worlds for large projects: simple modern code and backwards compatible support for old versions of browsers, etc.

Effectively it puts JW's solution into the function when Rob de la Cruz's Object.keys(obj) is not natively available.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ivan
  • 4,383
  • 36
  • 27