7

I have a Javascript object with some keys and values:

var obj = { 
    "key1" : "val1", 
    "key2" : "val2", 
    "key3" : "val3", 
    "key4" : ""
}

I want to iterate all keys and retrieving all values.

I tried 2 ways:

1) Using for(var key in keys)

var keys = Object.keys(obj);
for (var key in keys) {
    // ...
}

The problem with this solution is that keys object is an array, so I have to use obj[keys[key]]]. Not very pretty.

Furthermore, inspecting "key4", the return value is "0" instead of "" (empty).

2) Using forEach

Object.keys(obj).forEach(function(key){
    // ...
});

The problem in this case is that if I try to do:

Object.keys(obj).forEach(function(key){
    obj[key];  // <- obj is undefined !!
});

The "obj" variable is undefined in the foreach!

What's the best way to iterate in all keys for retrieving all values?

Thanks

Kev
  • 15,899
  • 15
  • 79
  • 112
Alessandro C
  • 3,310
  • 9
  • 46
  • 82
  • @PranavCBalan the index is second argument https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach – jcubic Apr 27 '16 at 08:38
  • 2
    Possible duplicate of [How to get all properties values of a Javascript Object (without knowing the keys)?](http://stackoverflow.com/questions/7306669/how-to-get-all-properties-values-of-a-javascript-object-without-knowing-the-key) – ADreNaLiNe-DJ Apr 27 '16 at 08:44

6 Answers6

10

Just use for in.

var obj = { 
  "key1" : "val1", 
  "key2" : "val2", 
  "key3" : "val3", 
  "key4" : ""
};

for (var key in obj) {

  console.log(key); // key1 and etc...
  console.log(obj[key]); // val1 and etc...
}
Ali Mamedov
  • 5,116
  • 3
  • 33
  • 47
  • 1
    Note that this is dangerous, as T.J. Crowder says, as it will also iterate over any inherited properties. For example, it will iterate five times instead of four if you do `Object.prototype.foo = "bar"`. – Amadan Apr 28 '16 at 02:30
  • You could secure this `for in` loop with `Object.hasOwnProperty()`, which checks if a given property is not inherited. – Eduardo Melo Jul 26 '17 at 14:30
7

In your first example, you're using for-in to loop through an array, which is not generally a good idea. To loop through arrays, this answer has lots of options for you.

If you want to loop through all of an object's keys, use for-in on the object:

for (var key in obj) {
    var value = obj[key];
    // ...
}

Note that you'll see both the object's own properties and also ones it inherits from its prototype. If you just want own properties, you could add a guard:

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        var value = obj[key];
        // ...
    }
}

...or use Object.keys (introduced in ES5, in 2009, so not on IE8; there's a shim if you need to support obsolete browsers like IE8):

Object.keys(obj).forEach(function(key) {
    var value = obj[key];
    // ...
});

In both cases, you'll only get the object's enumerable properties. If you need to include non-enumerable properties, reach for getOwnPropertyNames:

Object.getOwnPropertyNames(obj).forEach(function(key) {
    var value = obj[key];
    // ...
});

That will get the object's own (not inherited) property names, even if non-enumerable, as long as they're strings (which they always are in ES5 and earlier; in ES2015 and later, they're normally strings but can also be Symbol instances if you use Symbols).

getOwnPropertyNames was also introduced in ES5, but I don't think it can be shimmed, so you can't use it in IE8 or other obsolete browsers.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
4

Update:

Object.values() may do the job.

Alternate approach:

Using ES6, Object.keys(obj).map(key => obj[key]) will return an array containing all the values.

backslashN
  • 2,795
  • 3
  • 15
  • 25
3

Object.values() will provide an array of the objects property values.

 const object1 = {   a: 'somestring',   b: 42,   c: false };


 console.log(Object.values(object1)); // expected output: Array

 ["somestring", 42, false]

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values

Zeeshan Adil
  • 1,937
  • 5
  • 23
  • 42
0

It's strange that you have this problem of obj undefined, it shouldn't happens. Here it is another way to it, in addition of the other answers. It's useful only if you don't need filter something and you want just to have an array with all values (and few lines)

var values = []
  Object.keys(object)
    .every( (prop) => values.push(object[prop]))
Cris
  • 1
  • 1
0

I like the first approach much more than the second one, but there is no need to store the keys separately. Let's consider this example:

function parseValues(obj, operation) {
    for (key in obj) {
        operation(obj[key], key);
    }
}

As you can see we did not need to read the keys. You can use a function like this for any purposes. For example:

var myObject = {a: 1, b: 2, c: 3};

parseValues(myObject, function(item, key) {
    if (key !== "b") {
        if (item > 1) {
            myObject[key] = item * 2;
        }
    }
});

There are literally infinitely many ways you can use this like. In the second approach the forEach runs for the keys and not for the object whose keys you are parsing. You need to use getOwnPropertyNames, as T.J.Crowther has already pointed out.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175