JavaScript foreach loop on an associative array object
Asked Answered
N

11

222

Why is my for for-each loop not iterating over my JavaScript associative array object?

// Defining an array
var array = [];

// Assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";

// Expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var i = 0; i < array.length; i++) {
    console.log(array[i]);
}

jQuery each() could be helpful: https://api.jquery.com/jQuery.each/

Natiha answered 14/9, 2013 at 17:42 Comment(3)
You create an array but then use it as a map. It looks like you want a plain object instead.Gretta
There's no such things as associative arrays in JS: it's either plain Array or an Object. Nothing prevents adding non-numeric properties to Array, but that doesn't make it associative - in particular, length property won't auto-count these properties.Kelpie
re: There's no such things as associative arrays in JS. -- worded another way: JavaScript uses the name "Object" instead of the name "associative array". But it doesn't have a ".length" property.Sather
G
367

The .length property only tracks properties with numeric indexes (keys). You're using strings for keys.

You can do this:

var arr_jq_TabContents = {}; // no need for an array

arr_jq_TabContents["Main"] = jq_TabContents_Main;
arr_jq_TabContents["Guide"] = jq_TabContents_Guide;
arr_jq_TabContents["Articles"] = jq_TabContents_Articles;
arr_jq_TabContents["Forum"] = jq_TabContents_Forum;

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

To be safe, it's a good idea in loops like that to make sure that none of the properties are unexpected results of inheritance:

for (var key in arr_jq_TabContents) {
  if (arr_jq_TabContents.hasOwnProperty(key))
    console.log(arr_jq_TabContents[key]);
}

edit — it's probably a good idea now to note that the Object.keys() function is available on modern browsers and in Node etc. That function returns the "own" keys of an object, as an array:

Object.keys(arr_jq_TabContents).forEach(function(key, index) {
  console.log(this[key]);
}, arr_jq_TabContents);

The callback function passed to .forEach() is called with each key and the key's index in the array returned by Object.keys(). It's also passed the array through which the function is iterating, but that array is not really useful to us; we need the original object. That can be accessed directly by name, but (in my opinion) it's a little nicer to pass it explicitly, which is done by passing a second argument to .forEach() — the original object — which will be bound as this inside the callback. (Just saw that this was noted in a comment below.)

Gehlenite answered 14/9, 2013 at 17:42 Comment(8)
Whats this var arr_jq_TabContents = {};? I mean {}Natiha
@Ultra it is an empty object literal. It just means that the variable is initialized with a reference to a new empty object.Gehlenite
@Ultra you don't need an Array instance because in that code you're not using it like a JavaScript array. JavaScript does not have "associative arrays" like some other languages.Gehlenite
What is the difference between assigning [] and {}? Only the different prototypes?Accusal
@SoonDead well [] creates an Array instance, while {} creates an Object instance. Arrays are for numbered lists of properties, and the length is maintained. Not so for objects. (Well object properties can have numeric names, but there's no special meaning for those.)Gehlenite
'inheritance' advice was really helpful! Use it people!Natiha
Instead of using hasOwnProperty it should be possible in all modern web browsers to iterate over the keys of an object using: Object.keys(arr_jq_TabContents).forEach( function(key) { ... } );Horsehide
re: JavaScript does not have "associative arrays" like some other languages. -- worded another way: JavaScript uses the name "Object" instead of the name "associative array".Sather
C
103

This is very simple approach. The advantage is you can get keys as well:

for (var key in array) {
    var value = array[key];
    console.log(key, value);
}

For ES6:

array.forEach(value => {
  console.log(value)
})

For ES6 (if you want the value, index and the array itself):

array.forEach((value, index, self) => {
  console.log(value, index, self)
})
Cathiecathleen answered 14/3, 2015 at 2:35 Comment(6)
Don't use var in loops suggesting scoping which does not exist. Use var in front of the loop or let in the loop.Gaslight
@ceving, can you explain more on why not use var in loops? I come from C++/PHP background and I don't understand this. scoping does exist in the loop, but temporary, so I am not sure what you mean.Orang
@Orang In most languages a variable declaration in a for loop generates a scope limited to the body of the for loop. But in JavaScript a variable declared by var is always function global even if you write it in a for loop. See here: davidwalsh.name/for-and-against-letGaslight
not memory leaks per se, but definitely "memory spills". var in Javascript creates variables in memory even after the loop is done.Savior
I think the point of these comments regarding the use of "var" is to now use "let" in general but specifically in a loop. The reasons are explained above but in summary it's due to scope, "var" creates global scope.Disillusionize
foreach does not work with associative arraysParimutuel
B
14

If Node.js or the browser supports Object.entries(), it can improve upon Object.keys() (as in Pointy's answer).

const h = {
  a: 1,
  b: 2
};

Object.entries(h).forEach(([key, value]) => console.log(value));
// logs 1, 2

In this example, forEach uses destructuring assignment of an array.

Bajaj answered 11/2, 2019 at 8:48 Comment(1)
Wow great that was what I needed :DChinook
F
7

There are some straightforward examples already, but I notice from how you've worded your question that you probably come from a PHP background, and you're expecting JavaScript to work the same way -- it does not. A PHP array is very different from a JavaScript Array.

In PHP, an associative array can do most of what a numerically-indexed array can (the array_* functions work, you can count() it, etc.). You simply create an array and start assigning to string indexes instead of numeric.

In JavaScript, everything is an object (except for primitives: string, numeric, boolean), and arrays are a certain implementation that lets you have numeric indexes. Anything pushed to an array will affect its length, and can be iterated over using Array methods (map, forEach, reduce, filter, find, etc.) However, because everything is an object, you're always free to simply assign properties, because that's something you do to any object. Square-bracket notation is simply another way to access a property, so in your case:

array['Main'] = 'Main Page';

is actually equivalent to:

array.Main = 'Main Page';

From your description, my guess is that you want an 'associative array', but for JavaScript, this is a simple case of using an object as a hashmap. Also, I know it's an example, but avoid non-meaningful names that only describe the variable type (e.g. array), and name based on what it should contain (e.g. pages). Simple objects don't have many good direct ways to iterate, so often we'll turn then into arrays first using Object methods (Object.keys in this case -- there's also entries and values being added to some browsers right now) which we can loop.

// Assigning values to corresponding keys
const pages = {
  Main: 'Main page',
  Guide: 'Guide page',
  Articles: 'Articles page',
  Forum: 'Forum board',
};

Object.keys(pages).forEach((page) => console.log(page));
Fourteenth answered 12/2, 2017 at 13:26 Comment(0)
P
4

arr_jq_TabContents[key] sees the array as an 0-index form.

Prakash answered 5/8, 2016 at 11:45 Comment(0)
M
4

Here is a simple way to use an associative array as a generic Object type:

Object.prototype.forEach = function(cb){
   if(this instanceof Array) return this.forEach(cb);
   let self = this;
   Object.getOwnPropertyNames(this).forEach(
      (k)=>{ cb.call(self, self[k], k); }
   );
};

Object({a:1,b:2,c:3}).forEach((value, key)=>{ 
    console.log(`key/value pair: ${key}/${value}`);
});
Malfeasance answered 8/6, 2018 at 9:29 Comment(0)
H
2

This is (essentially) incorrect in most cases:

var array = [];
array["Main"] = "Main page";

That creates a non-element property on the array with the name Main. Although arrays are objects, normally you don't want to create non-element properties on them.

If you want to index into array by those names, typically you'd use a Map or a plain object, not an array.

With a Map (ES2015+), which I'll call map because I'm creative:

let map = new Map();
map.set("Main", "Main page");

you then iterate it using the iterators from its values, keys, or entries methods, for instance:

for (const value of map.values()) {
    // Here, `value` will be `"Main page"`, etc.
}

Using a plain object, which I'll creatively call obj:

let obj = Object.create(null); // Creates an object with no prototype
obj.Main = "Main page"; // Or: `obj["Main"] = "Main page";`

you'd then iterate its contents using Object.keys, Object.values, or Object.entries, for instance:

for (const value of Object.values(proches_X)) {
    // Here, `value` will be `"Main page"`, etc.
}
Heap answered 2/9, 2019 at 17:37 Comment(0)
E
2

You can do this:

var array = [];

// Assigning values to corresponding keys
array[0] = "Main page";
array[1] = "Guide page";
array[2] = "Articles page";
array[3] = "Forum board";


array.forEach(value => {
    console.log(value)
})

 

Earthnut answered 14/3, 2020 at 13:31 Comment(0)
L
1

var obj = {
  no: ["no", 32],
  nt: ["no", 32],
  nf: ["no", 32, 90]
};

count = -1; // Which must be a static value
for (i in obj) {
  count++;
  if (obj.hasOwnProperty(i)) {
    console.log(obj[i][count])
  };
};

In this code I used the brackets method for call values in an array because it contained an array. However, briefly the idea which a variable i has a key of property and with a loop called both values of the associative array.

It is the perfect method.

Lightsome answered 27/9, 2017 at 20:46 Comment(1)
You are not looping throwght an array, you are looping throught a object that has arrays in it's keys.. Please read the question and look at the example.Pontone
Y
1

It seems like almost every answer is not what was asked at the very first place.

It's seems bit off that foreach-loop does not work. and simple for-loop will not work as well because length property will be zero in case of associative arrays(one of the fallback). but for-in do the thing for associative array

// Defining an array
var array = [];

// Assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";

// Expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var index in array) {
    console.log(index,array[index]);
}
Yukikoyukio answered 14/3, 2022 at 18:5 Comment(0)
R
0
const myObject = {
name: "Alice",
age: 30,
city: "Wonderland"

};

Object.values(myObject).forEach((key) => { console.log(${key}); });

Riga answered 13/3 at 17:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.