tags:

views:

20213

answers:

12

Do you think there is a big difference in foreach and for loops? What kind of "for" do you prefer to use and why?

Let's say we have an array of associative arrays:

var myArray = [{'key': 'value'}, {'key': 'value1'}];

So we can iterate:

for (var i = 0; i < myArray.length; i++)

And:

for (var i in myArray)

I don't see a big difference. Are there any performance issues?

A: 

With for (var i in myArray) you can loop over objects too, i will contain the key name and you can access the property via myArray[i]. Additionaly, any methods you will have added to the object will be included in the loop, too, i.e., if you use any external framework like jQuery or prototype, or if you add methods to object prototypes directly, at one point i will point to those methods.

Nouveau
+2  A: 

I'd use the different methods based on how I wanted to reference the items.

Use foreach if you just want the current item.

Use for if you need an indexer to do relative comparisons. (I.e. how does this compare to the previous/next item?)

I have never noticed a performance difference. I'd wait until having a performance issue before worrying about it.

Matt Lacey
See Bnos answer below - for...in isn't doing what you expect here and if you use it you may well have all kinds of fun. For the record, Prototype does things the *right* way.
marcus.greasly
+49  A: 

The choice is best made based on the which idiom is best understood.

An array is expected to be iterated using:-

for (var i = 0; i < a.length; i++)
   //do stuff with a[i]

An object being used an associative array is iterated using:-

for (var key in o)
  //do stuff with o[key]

I would recommend that despite there being alternatives unless you have earth shattering reasons otherwise you should stick with the established pattern of usage.

AnthonyWJones
It should be mentioned that it is a nice practice to use for...in with filtering if statement. There is a handy method of Object "obj.hasOwnProperty(member)" which checks if a member returned by iterator is actually member of the object. See: http://javascript.crockford.com/code.html
Damir Zekić
As commented at another answer(s), the "for...in" does not work correctly for Arrays, as it will iterate over all Array properties and methods. Thus, you should use "for...in" only for iterating over object properties. Otherwise, stick to "for(i=0; i<something; i++)"
Denilson Sá
+10  A: 

there are performance differences depending on what kind of loop you use and on what browser.

For instance:

for (var i = myArray.length-1; i >= 0; i--)

is almost twice as fast on some browsers than:

for (var i = 0; i < myArray.length; i++)

However unless your arrays are HUGE or you loop them constantly all are fast enough. I seriously doubt that array looping is a bottleneck in your project (or for any other project for that matter)

Gene
Would storing "myArray.length" into a variable before looping make the performance difference go away? My guess is "yes".
Tomalak
It would make at least most of it go away. However if I remember correctly i-- is marginally faster than i++. In any case the differences are very small.
Gene
But we are still talking JavaScript here, not assembler, aren't we? :-)
Tomalak
I'm not sure anymore :D I know I was but don't know about you
Gene
'.' is quite appallingly poor performance in JS (or, at least, IE7 JS), in my experience; it's worth strength-reducing for it, as here.
ijw
No. 'myArray.length' is a property, not a method on an object--no calculation is done to determine its value. Storing its value in a variable will do nothing at all.
jason
Yes there is. Properties are not variables; they do have get/set code.
ste
I tend to use `for(var i = myArray.length; i--;)`
Kevin
+2  A: 

For in loops on Arrays is not compatible with Prototype. If you think you might need to use that library in the future, it would make sense to stick to for loops.

http://www.prototypejs.org/api/array

Chase Seibert
Forget "you might need to use that library". Think instead "your JS might be included with *anything else* that uses that library", because the problems still come.
ijw
+6  A: 

I second opinions that you should choose the iteration method according to your need. I would suggest you actually not to ever loop through native Array with for in structure. It is way slower and, as Chase Seibert pointed at the moment ago, not compatible with Prototype framework.

There is an excellent benchmark on different looping styles that you absolutely should take a look at if you work with JavaScript. Do not do early optimizations, but you should keep that stuff somewhere in the back of your head.

I would use for in to get all properties of an object, which is especially useful when debugging your scripts. For example, I like to have this line handy when I explore unfamiliar object:

l = ''; for (m in obj) { l += m + ' => ' + obj[m] + '\n' } console.log(l);

It dumps content of the whole object (together with method bodies) to my Firebug log. Very handy.

Damir Zekić
Nice benchmark in the link.
HRJ
+21  A: 

Douglas Crockford recommends in JavaScript: The Good Parts (page 24) to avoid using the for in statement.

If you use for in to loop over property names in an object, the results are not ordered. Worse: You might get unexpected results; it includes members inherited from the prototype chain and the name of methods.

Everything but the properties can be filtered out with .hasOwnProperty. Javascript: The Good Parts presents this code sample which does what you probably wanted originally:

for(name in object)
{
    if (object.hasOwnProperty(name))
    {
    }
}
Bno
Second that - foreach... isn't doing what you might expect (esp if coming from .net) and it's probably not what you're trying to do.
marcus.greasly
for...in is perfectly appropriate for looping over object properties. It is not appropriate for looping over array elements. If you can't understand the difference between these scenarios, then yes, you should avoid for...in; otherwise, go nuts.
Shog9
Want to emphasize the fact that it is NOT ORDERED! This could be a big problem, and would be difficult bug to catch.
Jason
In theory it's not ordered, but in all modern browsers, it is (except in some weird cases in Chrome, apparently). I believe future JavaScripts will have guaranteed ordering.
Nosredna
+1 for "it includes members inherited from the prototype chain and the name of methods." You'll have fun if someone happens to use your code with Prototype loaded (even if your code doesn't actually use it), for instance.
ijw
Please don't forget to **declare** the `name` variable: `for(var name in object)...`, otherwise, if that code is inside a function for example, the `name` variable end up being a property of the global object (an assignment to an *undeclared identifier* does that), also in the new ECMAScript 5 Strict Mode, that code will throw a `ReferenceError`.
CMS
A: 

I have seen problems with the "for each" using objects and prototype and arrays

my understanding is that the for each is for properties of objects and NOT arrays

Benjamin Lee
A: 

i think foreach doesnt work in IE6

01
+1  A: 

here is something i did.

function foreach(o, f) {
 for(var i = 0; i < o.length; i++) { // simple for loop
  f(o[i], i); // execute a function and make the obj, objIndex available
 }
}

this is how you would use it
this will work on arrays and objects( such as a list of HTML elements )

foreach(o, function(obj, i) { // for each obj in o
  alert(obj); // obj
  alert(i); // obj index
  /*
    say if you were dealing with an html element may be you have a collection of divs
  */
  if(typeof obj == 'object') { 
   obj.style.marginLeft = '20px';
  }
});

I just made this so I'm open to suggestions :)

+10  A: 

FYI - jQuery Users


jQuery's each(callback) method uses for( ; ; ) loop by default, and will use for( in ) only if the length is undefined.

Therefore, I would say it is safe to assume the correct order when using this function.

Example:

$(['a','b','c']).each(function() {
    alert(this);
});
//Outputs "a" then "b" then "c"

The downside of using this is that if you're doing some non UI logic, your functions will be less portable to other frameworks. The each() function is probably best reserved for use with jQuery selectors and for( ; ; ) might be advisable otherwise.


Jason
A: 

If you really want to speed up your code, what about that?

for( var i=0,j=null; j=array[i++]; foo(j) );

it's kinda of having the while logic within the for statement and it's less redundant. Also firefox has Array.forEach and Array.filter

fabjoa