Tuesday, August 18, 2009

for -> in loops with JavaScripts

I love for loops... don't think I could live without them! The problem with JavaScript is that you don't always have a numerically indexed array of elements that you need to loop through. These are often referred to as Associative Arrays. JavaScript simply treats them as Objects. They are VERY simple to use and usually easy to loop through... simply use the for -> loop syntax:

var fruitColorArr = {
for(var i in fruitColorArr){
alert(fruitColorArr[i]+"'s are "+i);

This will result in three alerts:
"apple's are red", "banana's are yellow", and "lime's are green".

Simple right? Wrong!!! There is a little problem called prototyping that can destroy this whole scenario! Let's imagine someone added the following JavaScript to their page to supplement the Object object:

Object.prototype.test = function(){alert('hi');}

It's a great feature of JavaScript and attests to it's amazing flexibility.... It gives us the power to call:


And have it alert "hi".

The problem arises when you try to then run the for in loop on the fruitColorArr... We get the following alerts:

"apple's are red",
"banana's are yellow",
"lime's are green"
"function () {
}'s are new"

Seems relatively harmless for this example, but it can be disastrous in a larger application, not to mention really hard to tack down!

So how do you work around it??? Test everything!!!

If you know the type of element you are expecting, test for it! If you are expecting a string, use the following:

for(var i in myArr){
if(typeof(myArr[i]) == 'string'){
/* loop code goes here */

If you are not sure what type of element to expect, at least test to make sure what you have is not a function.... At the very least, I use the following:

for(var i in myArr){
if(typeof(myArr[i]) != 'function'){
/* loop code goes here */

By doing this, you can be sure that no matter where your code is used, it will not cause strange behavior!

No comments: