66

I have a standard jQuery plugin set up that creates default settings at the top:

jQuery.fn.myPlugin = function(options) { 
    var defaults = {  
        starts: "0px,0px",
        speed: 250, ...
    };
    o = $.extend(defaults, options);
}

I have another variable called numberOfObjects.

I'm trying to loop through the default variables. For each object found (from numberOfObjects) I need to duplicate the value of the variable value. So, if the numberOfObjects variable is 3, the defaults.starts should be 0px,0px > 0px,0px > 0px,0px. The & gt; is used to split values.

This is what I currently have. X represents the variable name inside defaults. Y represents the variable for the current value of x. I've gotten this far and have no clue what to do next.

for (x in defaults) {   // x is defaults.x
    defaults.x = defaults.x + " > y";
}
Makyen
  • 31,849
  • 12
  • 86
  • 121
Aaron
  • 2,482
  • 1
  • 26
  • 56

8 Answers8

118
var obj = {
    'foo': 1,
    'bar': 2
};

for (var key in obj) {
    console.log(obj[key]);
}

Or with jQuery:

$.each(obj, function(key, value) {
    console.log(this, value, obj[key]);
});
Petah
  • 45,477
  • 28
  • 157
  • 213
  • 7
    The problem with this method that you also should check if the property belongs to object itself rather than its prototype. I suggest using @blair-anderson solution with `Object.keys(obj)` – ivstas Sep 21 '15 at 08:42
  • 3
    @Kite while true, the question specifically asked about `object literals` – Petah Sep 22 '15 at 02:11
  • 3
    This solution lacks `guard-for-in`: http://eslint.org/docs/rules/guard-for-in - Using `Object.keys(obj).forEach(func)` is the way better solution (see Blair Anderson's post). – Timo Ernst May 25 '17 at 11:46
  • 1
    @Timo as per the above comments, this question was specifically asking about `object literals`, not instances. – Petah May 25 '17 at 21:21
  • @petah So did I. When I use the code above with literals, ESLint complains with the error mentioned. – Timo Ernst May 25 '17 at 21:24
  • 1
    @zero_cool yes. And as per my example `obj[key]` gives you the value. – Petah Aug 21 '17 at 11:39
57

You should not have to depend on jQuery for this.

Object.keys(obj).forEach(function (key) {
  var value = obj[key];
   // do something with key or value
});
Blair Anderson
  • 19,463
  • 8
  • 77
  • 114
  • Also go to the link for the polyfill if you need to support IE less than 9. – Greg Dec 08 '14 at 06:47
  • 2
    According to AirBnB styleguide with ESLint, this is the preferred way over `for (var key in obj)` – Timo Ernst May 25 '17 at 11:40
  • 1
    @Timo - the reason being that Object.keys looks up all its own, enumerable properties. 'for in' additionally looks up inherited enumerable properties, not only its own ones. – dannymac Sep 01 '18 at 01:29
19

Let's setup our basic object before we get started:

const x = {
  x: 1,
  y: 2,
  z: 3
};

We can use Object.keys(x) to return an array of all of the keys within our object.

Object.keys(x)
> ['x', 'y', 'z']

Now we able to map, filter, reduce and loop over our array and do something with that value within our object:

Object.keys(x).map(key => x[key] + 1)
> [2,3,4]

Object.keys(x).forEach(key => console.log(x[key]))
> [1,2,3]

The main take away here is that we have to use the key to access that specific value, it works but it feels a little clunky. ES2017 brings with it Object.values() which can be used as a nice shortcut for returning an array of all of the values within an Object.

Object.values(x)
> [1,2,3]

Object.values(x).map(value => value + 1)
> [2,3,4]

Object.values(x).forEach(value => console.log(value))
> [1,2,3]

You can read more about Object.values() at MDN, they also include a polyfill, should you need to support older browsers & browsers which haven't yet implemented it.

There's also Object.entries() which conveniently allows you to access the keys and the values. It returns an array containing arrays (first item being the key and the second item being the value.

Object.entries(x);
> [['x', 1], ['y', 2], ['z', 3]]

We can use de-structuring to easily get at these values:

Object.entries(x).map(([key, value]) => console.log(key, value))
Kristian Roebuck
  • 3,209
  • 2
  • 21
  • 29
12

To iterate over an object's values you can use a for...of loop with Object.values.

const myObj = {a: 1, b: 2}

for (let value of Object.values(myObj)) {
    console.log(`value=${value}`)
}

// output: 
// value=1
// value=2

If you want the key and value when iterating, you can use Object.entries.

const myObj = {a: 1, b: 2}

for (let [key, value] of Object.entries(myObj)) {
    console.log(`key=${key} value=${value}`)
}

// output: 
// key=a value=1
// key=b value=2
Derek Soike
  • 11,238
  • 3
  • 79
  • 74
9

Best practice is to validate if the object attribute that is being iterated over is from the object itself and not inherited from the prototype chain. You can check this using .hasOwnProperty(): (Of course if you do want to include inherited properties just remove the if statement).

Here is the general case:

for(var index in object) { 
   if (object.hasOwnProperty(index)) {
       var value = object[index];
       // do something with object value here.
   }
}

Here is the example case you mentioned where you want to create a duplicate object with the value of each key duplicated replicated according to the value of the var numberofobjects (i've added in two solutions whereby you either modify the existing object or create a new one):

// function to repeat value as a string inspired by disfated's answer here http://stackoverflow.com/questions/202605/repeat-string-javascript

function repeatValue(value, count) {
    value = String(value); // change to string to be able to add " > " as in question
    if (count < 1) return '';
    var result = '';
    while (count > 1) {
        if (count & 1) result +=  value + " > ";
        count >>= 1, value += " > " + value;
    }
    return result + value;
}

var numberofobjects = 3;
var newObject = {}; // for use if creating a duplicate object with the new values

for(var x in defaults) { 
   if (defaults.hasOwnProperty(x)) {
       //use this to replace existing values
       defaults[x] = repeatValue(defaults[x], numberofobjects);

       //or use this to create values in the new object
       newObject[x] = repeatValue(defaults[x], numberofobjects);
   }
}
David
  • 3,166
  • 2
  • 30
  • 51
5

In your code:

for(x in defaults){
   defaults.x = defaults.x + " > y";
}

You need to say defaults[x] instead of defaults.x.

x is a variable holding a string that is the key into the defaults object, and the bracket (array-style) syntax lets you use that variable to get the property. With the dot notation defaults.x is looking for a property actually called "x", the equivalent of defaults["x"].

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • Ok, I'm confused. If I log console.log(defaults[starts]) I get absolutely nothing, but if I log console.log(defaults.starts) it pulls the string. The x is just a stand-in variable that I need to assign 'starts', 'speed', etc. to within the loop through defaults - so I get defaults.starts and defaults.speed, etc. Am I setting up the defaults section incorrectly? Thanks! – Aaron Feb 20 '12 at 03:38
  • Dot notation works with the actual name of the property, so in your example `defaults.starts` works because you have a property name that is the string "starts". The equivalent bracket notation is `default["starts"]` - note the quotes. The bit inside the square brackets should be any JS expression that returns a string so if you say `defaults[starts]` is looking for a variable `starts`, which you don't have so that returns undefined. Read this: https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects – nnnnnn Feb 20 '12 at 03:53
2

var yourVariable = {
  Bobe: 23,
  Pope: 33,
  Doop: 43,
  Dope: 53
};

for(var keyName in yourVariable){
 document.write(keyName, " : ",yourVariable[keyName]," ");
};
Prem Gurusamy
  • 331
  • 2
  • 5
0

Taken from Mozilla:

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

console.log(Object.values(object1));
// expected output: Array ["somestring", 42, false]
satnam
  • 10,719
  • 5
  • 32
  • 42