views:

167

answers:

2

I apologize in advance if this is a stupid question that betrays my lack of understanding of javascript/programming.

I've been using $.each to do iterations for a while now, but I keep on hearing people say to use native JS for to do loops. I'm very concerned about performance but I am not sure if it's always possible to replace $.each with for in a meaningful way.

So my questions are, is it possible to always replace $.each with for, and if not what's the rule of thumb for when it can be done and when it cannot.

I have an each like this:

 $this.find("div.class").each(function (){
  var $thisparent = $(this).parent();

  if (condition) {          
   $(this).prepend($thisparent.text());
  }

  if (condition2) {          
   $(this).prepend($thisparent.text());
  }

 });
+3  A: 

Someone compared the performance of for and $.each:

http://jquery-howto.blogspot.com/2009/06/javascript-for-loop-vs-jquery-each.html

karim79
So apparently you only take a substantial performance hit with large arrays. Good to know.
Joel Potter
I think the reason behind this is the overhead of function calls, as jQuery's `each` code isn't that heavy at all.
strager
Then what about this:http://www.youtube.com/watch?v=mHtdZgou0qU#t=24m00s
Mark
@Mark - great video link, thanks for that :)
karim79
@Joel: Well, it's substantial in the sense that jQuery takes twice as long (with array size of one million). But the difference is only 600ms which is nothing, really.
DisgruntledGoat
But as we all know: Many a mickle makes a muckle. ^^
anddoutoi
@anddoutoi - +1 for "Many a mickle makes a muckle"
karim79
+3  A: 

This is what jQuery does with .each, basically:

$.fn.each = function(callback) {
    var i, length = this.length;
    for(i = 0; i < length; ++i) {
        callback.call(this[i]);
    }
};

So it's not hard to substitute your anonymous function's 'contents' with the callback.call call. Just be sure to replace this with a temporary with the jQuery object.

Converting your supplied code:

var foo = $this.find("div.class"),
    fooLength = foo.length,
    i,
    $thisparent;

for (i = 0; i < fooLength; ++i) {
    $thisparent = $(foo[i]).parent();

    if (condition) {          
        $(foo[i]).prepend($thisparent.text());
    }

    if (condition2) {          
        $(foo[i]).prepend($thisparent.text());
    }
}

For additional (potential) speed, cache foo[i] into a temporary. too, and assign $thisparent only when needed. If condition and condition2 are mutually exclusive, use a single if (condition || condition2).

strager
Thanks a lot, but can you please provide an example?Thanks.
Mark
Thank you so much, :) great answer and thanks for increasing my understanding. Can you demonstrate how to use a single if? Also what if I have half a dozen mutually exclusive conditions.
Mark
@Mark, Read up on the || operator (https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Logical_Operators).
strager
Oh I see what you mean. The actions to take upon conditions aren't the same for me though, so that's why I didn't realize what you were implying.
Mark