4

Today i'm very stack with a Work and jQ. I was get a morning for it but i can't resolve it :(. My Work here:

<div class="container">
    <p class="test">a</p>
    <div>
        <p class="test">a</p>
    </div>
</div>

In normal, i can using jQ with each function for select all <p class="test">a</p> EX:

$(".test").each(function() {
    $(this).text('a');
});

But i hear everyone talk that, for function get a less timeload than each function. Now i want using for instead of each.. but i don't know how to write code jQ in this case.

Somebody can help me!. thankyou!

1
  • Why do you want less time load? Is it a very consuming operation? The rule for javascript is that if its not lagging, and there arent an excessive amount of errors, its good code.
    – tcooc
    Commented Jun 19, 2010 at 3:50

5 Answers 5

7

I wouldn't worry about it unless you were iterating through hundreds of them.

for loop is usually used with normal DOM (aka without jQuery) traversing, like...

var elements = document.getElementById('something').getElementsByTagName('a');

var elementsLength = elements.length;

for (var i = 0; i < elementsLength; i++) {

    elements[i].style.color = 'red';
}

Caching of elementsLength is a good idea so it is not calculated every iteration. Thanks to CMS for this suggestion in the comments.

Just adapt that for your jQuery object if you wanted to do it with jQuery.

Replace elements variable with your jQuery collection, like $('#something a'). I think you may need to rewrap the object if you need to do any more jQuery stuff with it.

5
  • last time I checked getElementById returned one html element, which hadn't had any methods like getElementsByTagName. That is only what document had. Long story short I don't think it's possible to chain methods like that with native javascript methods Commented Jun 19, 2010 at 3:50
  • 2
    His code is correct. You may use any DOM element as context to descend with a getElementsByTagName or getElementsByClassName like that.
    – Dave Ward
    Commented Jun 19, 2010 at 3:53
  • @alex: The condition of your loop should be i < elements.length since elements[elements.length] will be undefined (they are 0-based) otherwise you'll get a TypeError at the last iteration, also when working with HTMLCollections is a good idea to cache the value of length property, because accessing that value on each iteration is expensive, since HTMLCollections are "live". E.g. for(var i = 0, n = elements.length; i < n; i++) Commented Jun 19, 2010 at 3:53
  • yea, all guys answer is right. I think code of every is similar. also this is right code :). thankyou all :)
    – Rueta
    Commented Jun 19, 2010 at 3:56
  • @CMS I knew cacheing the length was a good idea, but wasn't sure if adding it would cloud the most important thing - the actual traversal. Still, I included it :)
    – alex
    Commented Jun 19, 2010 at 3:57
5

One thing to watch out for is that using an ordinal accessor on the result of a jQuery selection will return a native DomElement. If you want to use jQuery methods on them, you have to re-wrap them:

var testElements = $('.test');

for (var i = 0; i < testElements.length; i++) {
  // Using $() to re-wrap the element.
  $(testElements[i]).text('a');
}

I'd second what others have said though. Unless you're dealing with many elements, this is premature optimization. Re-wrapping the elements to use the .text() method may even bring it back to no gain at all.

2
  • +1 for "Re-wrapping the elements to use the .text() method may even bring it back to no gain at all.". I don't have any benchmarks, but it sounds cumbersome to rewrap every iteration.
    – alex
    Commented Jun 19, 2010 at 4:02
  • 2
    Re-wrapping is the $(element) step within the loop. That's necessary if you still want to be able to use jQuery's methods on each element, but it comes at a performance cost for each iteration (as jQuery much construct a new jQuery object to wrap that element with its extended functionality).
    – Dave Ward
    Commented Jun 19, 2010 at 4:17
1

have you tried the obvious solution?

var nodes = $(".test");
for(var i = 0; i < nodes.length; i++)
{
    var node = nodes[i];
}
3
  • The for block is not a closure, so you would be technically redefining the same variable on each loop. Not sure, but I think that throws an error. Commented Jun 19, 2010 at 3:54
  • Variable declarations are "hoisted" to the top, so what it actually looks like is this: var nodes, node; nodes = $('.test'); for (...) { node = nodes[i]; }
    – Casey Chu
    Commented Jun 19, 2010 at 4:38
  • why would I reference same element. nodes is a array of html elements. i-th element in this collection is one of found elements with class test. I don't see a problem here Commented Jun 19, 2010 at 5:47
1

This article shows that each() has no significant performance penalty until you get into the hundreds of thousands of looped-over items.

1
  • 1
    That's commendable, but this would be a trivial performance gain at the cost of decreased code clarity and maintainability. I'd bet there are bigger performance hogs elsewhere. Like Something.length in a for loop maybe? ;-) Commented Jun 19, 2010 at 4:02
1

Another alternative:

for (var i = 0; i < $('.test').length; i++){
    var element = $('.test').eq(i);
}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.