Using forEach vs for(var key) with an associative array - javascript

I just want to know why forEach doesn't work on an associative array:
var array =[];
array['W'] = 0;
array['S'] = 1;
// This doesn't work
console.log(array);
array.forEach(function(item){
console.log(item);
});
// This does
for(var key in array){
console.log(array[key]);
}

Array.prototype.forEach is defined by the standard to iterate over index members.
for-in enumerates all object properties.
So in short, the answer to your "why" question is: because the standard says so.

Probably because array.length evaluates to 0. You could use Object.values(array).forEach to iterate over the actual values of the array.

Related

Iterating JavaScript object with strings as keys

I am building a JavaScript array, which has strings as keys.
The array should have an object at every entry. My object looks like this (a console.log of my variable rIds):
Now, the length of this object is 0, which makes it impossible to iterate it.
I want to iterate every key, so I can retrieve and access my list of ids (rIds[key].productIds).
Code:
var rIds = [];
var response = RR.data.JSON.placements;
console.log(response);
$(response).each(function (placementId) {
var placement_name = this.placement_name;
rIds[this.placement_name] = {
productIds: []
};
$(this.recs).each(function (recIndex) {
var pid = this.pid;
pid = getRandomId(19341610, 19341746);
rIds[placement_name].productIds[recIndex] = pid;
});
});
var count = '<%=ViewBag.Get("RecommendationCount") %>';
console.log(rIds);
console.log(rIds.length);
$.each(rIds, function (index, val) {
console.log(val); // This should work as expected.
});
What did I try?
I found the following snippet, which does not work in IE8. However, this does not really help be, even though Object.keys(rIds).length results in the correct length.
for (var index = 0; index < Object.keys(rIds).length; index++) {
console.log(rIds[index]);
}
However, this code does not make my access the object.
Tl;dr & question
How do I iterate my JavaScript object which has strings as keys, so I can access the individual entries?
The Object.keys() function returns an array containing the property names of the object.
var keys = Object.keys(rIds);
for (var i = 0; i < keys.length; ++i) {
console.log(rids[keys[i]]); // object value
}
Alternatively, you can use the .forEach() method:
Object.keys(rIds).forEach(function(key) {
console.log(this[key]);
}, rIds);
Finally there's the venerable for ... in loop:
for (var key in rIds) {
if (rIds.hasOwnProperty(key))
console.log(rIds[key]);
To support versions of IE before IE9 you're kind-of stuck with for ... in, though you can find mostly-correct "polyfills" for Object.keys() and Array.prototype.forEach() at MDN.
To supplement Pointy's answer, you can also use jQuery's $.each (since you're already using jQuery elsewhere) to iterate over each key/value pair in your rIds object:
$.each(rIds, function(key, value) {
console.log(value);
});

JavaScript - Array behaves like object

I'd like to ask a question about JavaScript arrays.
Does the array behave like an object when we use for..in loop to iterate. I mean in this case can indexes take the role of properties(keys).
While you can do for..in syntax on an array, you shouldn't because you will will iterate over any properties you may have assigned to the array.
Example:
var array = [0, 1];
array.three = 2;
for (var p in array){
console.log(array[p]); //print 0, 1, 2
}
for(var i = 0; i < array.length; i++){
console.log(array[i]); //prints 0, 1
}
So, when dealing with arrays you should always use the for var i approach to avoid running into unexpected behavior.
As everything in JS, an array is an object.
It means you can use an array as a prototype :
var obj = Object.create([]);
console.log(obj instanceof Array); // true
obj[0] = "value 1";
obj.test = "value of property test";
for(var i in obj) console.log(obj[i]); // "value 1" "value of property test"
or any other thing you would do with an object, including using a for ... in loop.
However, the length property is updated with the highest (integer) index of the array +1.
var arr = ["one","two"];
arr.length; // 2
That's why it's preferred not to use for ... in loops when you only want to iterate on the values of the array : you can use for(var i=0,var l=arr.length;i<arr.length;i++) instead.
Yes ,you can access array like an object Only if array keys are string,
var sdf = [];
sdf['asd'] =45;
sdf[32] =8674;
console.log(sdf.asd) // WORKS
console.log(sdf.32) // Error
Array.prototype.forEach is what you want. Just be mindful of browser support or use a framework that corrects for unsupported browsers: http://kangax.github.io/compat-table/es5/#Array.prototype.forEach
for in should be used for iterating over object properties because order is not guaranteed.

Get the length of an array within a JSON object

I want to find out how many items are in my JSON object. I have seen many answers but they all deal with a common value to loop through. I am wanting the results to tell me that there are 2 items in this object. Any help would be great!
[{"manager_first_name":"jim","manager_last_name":"gaffigan"}]
You could use Object.keys in newer browsers. It would return an array of all the keys in the object, and that array would have a length property that will tell you how many items there are in the object :
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var length = Object.keys(arr[0]).length;
FIDDLE
In non-supporting browsers, you have to iterate
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var i = 0;
for (var key in arr[0]) i++;
FIDDLE
You can do this:
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}],
length = 0,
obj = arr[0]; // Get first obj from array
for(var k in obj){
if( obj.hasOwnProperty(k) ) {
length++;
}
}
console.log(length); // Shows 2
You should use hasOwnProperty because you can also extend an Object with functions, there could otherwise also be count als keys.
Links:
hasOwnProperty
Try
var jsonArr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var itemCount = JSON.stringify(jsonArr).split('":"').length - 1;
This is, of course, a rather coarse(and unreliable) way of doing it, but if you just want the item count, this should work like a charm.

for..in loop over an Array iterates also over the prototype functions

I've got a serious bug, which I've never seen before. First of all I've a simple Array:
var myArray = ["123", "456", "789"]
Now I want to iterate over this Array with a for..in - loop:
function mapData(list) {
for ( var i in list) {
var item = list[i];
if (item) {
// do something
}
}
}
After calling the method with mapData(myArray), firebug shows in the debugger this:
Loop: i = 0; item = 123;
Loop: i = 1; item = 456;
Loop: i = 2; item = 789;
Loop: i = compare;
Loop: i = union;
Loop: i = remove;
Loop: i = select;
Loop: i = contains;
So I think that are the prototype functions. But why? Any Ideas?
As I mentioned, I've never seen this before...
Do not use for..in to iterate over Array. This will iterate over all enumerable properties of the Array object and may not iterate over them in order. There are two alternatives:
Array.forEach (not supported by IE8-, although there is probably a shim).
A simple for loop
That's not a bug, you're just iterating over all enumerable array properties, and a library you use added functions to Array.prototype like this :
Array.prototype.union = function(...)
The library can be fixed by making the functions not enumerable by setting them using defineProperty :
Object.defineProperty(Array.prototype, 'union', {value:function(){...}});
But you should never use for..in to iterate over an array.
Iterate like this :
for (var i=0; i<list.length; i++) {
or like this:
for (let item of list) {

for( … in …) not working with array

I'm somehow confused:
I have a list of commands like this:
var commands = [{"command": "read"}, {"command": "write"}, {"command": "login"}];
If I try it access one of the commands like this it works:
console.log(commands[0]["command"]); // Output is "read"
console.log(commands[0].command); // Output is "read"
But if I try this the output is always undefined:
for(command in commands)
console.log(command["command"]); // undefined, undefined, undefined
for does an array iteration in javascript, so you want:
for(command in commands)
console.log(commands[command]["command"]);
ie, the command variable in your example is an array index, not the enumerated item from the array.
The for ... in construct iterates over the keys of the objects in the array, not the objects themselves. So you would need to write:
for(index in commands)
console.log(commands[index]["command"]);
The for (.. in ..) construct is for looping over objects, not arrays. Since you have an array of objects, you should be doing:
for (var i = 0, j = commands.length; i < j; i += 1) {
console.log(commands[i].command);
}
For a thorough explanation as to why you should use this for construct instead of the for...in, see answer #3010848.
Why use for..in with an array? Just access by index, and you also avoid potential problems of prototype extensions (see hasOwnProperty)
var i,len=commands.length;
for (i=0;i<len;i++ ) {
console.log commands[i].command
}
If order does not matter, more concisely
for (i=commands.length-1;i>=0;i-- ) {
}
Or
var i=commands.length;
while (i--) {
...
}
Use it like this
for(var x in commands)
console.log(commands[x].command);
Have you tried:
for(command in commands[0]) {
console.log(command["command"]);
}

Categories

Resources