View Full Version : for...in loop problem

May 8th, 2011, 02:37 PM
Hi all.

Here's my js:

var buttons = document.getElementById("mini_gallery").getElementsByTagName('a');
for (i in buttons) {buttons[i].onclick = show_mini_picture;}

function show_mini_picture() {

for (i=0;i<buttons.length;i++) {
buttons[i].style.color = "white";

/*for (i in buttons) {buttons[i].style.color = "white";}*/


The question is: could anybody explain to me why the commented out loop for (i in buttons) {buttons[i].style.color = "white";} doesn't work (even when it's not commented out!) but the traditional for loop above it does? The first for..in loop (on the second line of code) works fine. The second just tells gives me the error message "buttons[i].style is undefined".



May 8th, 2011, 02:38 PM
Try this.

for(i in buttons) {if(buttons[i]) {buttons[i].style.color = "white";}}

May 8th, 2011, 02:46 PM
Thanks for the quick reply, but that doesn't work either. Same error message!


May 8th, 2011, 02:58 PM
The for..in looping structure is intended to enumerate the properties on an object, or to iterate through an array. But 'buttons' is both an array and an object so you will struggle to get this to work.

for (i in buttons) {buttons[i].style.color = "white";}
in this, 'i' is not a number/index and so the reference to 'buttons[i]' is incorrect.

for (i in buttons) {i.style.color = "white";}
might possibly work, but I would recommend not using it: use for(..) instead.

May 8th, 2011, 03:08 PM
What's the error?

May 8th, 2011, 03:23 PM
An object like this {"demo":"hello world","test":"john doe"} would use this for loop.

for(i in arr) {
if(arr[i]) {
alert(i+': '+arr[i]);
But an array like this ['hello world','john doe'] would use this for loop.

for(i=0;i<arr.length;i++) {
if(arr[i]) {
alert(i+': '+arr[i]);
The first loop would return two alerts reading "demo: hello world" and "test: john doe" but the second loop would return again two alerts but this time reading "0: hello world" and "1: john doe".

Only use for-in when dealing with objects not arrays because objects use strings (sometimes numbers) to form the key where as arrays only use numbers to form the key, for loops use "i=0" for example which if searching an object it will try to process strings as numbers but will in return throw out an error as it will not return the correct data.

May 8th, 2011, 05:21 PM
where as arrays only use numbers to form the key..
is not correct: we can create an associative array and iterate the elements using a for.. in loop.

var myObj = { 'a' : 'red', 'b' :'green','c' : 'blue' };
var myArray = ['pink','grey','yellow'];
var myAssoc = [], x;

myAssoc['d'] = 'blue';
myAssoc['e'] = 'cyan';
myAssoc['f'] = 'brown';

for ( x in myObj )
alert(x + ' ' + myObj[x]);
for ( x in myArray )
alert(x + ' ' + myArray[x]); // uses the index
for ( x in myAssoc )
alert(x + ' ' + myAssoc[x]); // uses the key
But the use of for..in should generally be avoided:

It may (or may not) iterate through all inherited properties of an object
We cannot rely on the order of the iteration
Not every browser successfully implements iterating through an array
It can have a large overhead.

May 8th, 2011, 05:26 PM
Thanks all; I get the message that I should avoid the for...in method. But, nobody has explained why it works the first time I do a for..in loop on the array/object buttons, but not the second time.


May 8th, 2011, 05:46 PM
When you store a collection of DOM elements in a variable it is a special kind of thing that is both an array and an object.

for (i in buttons) {buttons[i].style.color = "white";}
is looping through all the properties of this thing called buttons, one is which is called 'length' - the number of items. 'length' doesn't have a style property, and in FireFox I receive an error 'buttons[i].style' is undefined.

The for..in loop that assigns an 'onclick' event to each button may complete in some browsers, or it may generate an error that the browser chooses to ignore.

(The list, and order, of the properties for 'buttons' that each browser loops through will/may be different.)