-2

I have JS generated html part, that looks like this:

<div id="container">
    <div id="block_1" class="blocks"></div>
    <div id="block_2" class="blocks"></div>
    <div id="block_3" class="blocks"></div>
    ...
    <div id="block_n" class="blocks"></div>
</div>

I am looping through them like this:

var blocks = $(".blocks");
$.each(blocks, function() {
      var val = $(this).text();
      ...
});

But I can also go:

for (var i=1; i<=block_count; i++) {
    var val = $("#block_"+i).text();
    ...
}

So the question is: Which way would be better performance-wise and is there any significant difference?
And maybe there is another - better way?!
max block count is about 10`000, but it's theoretically infinite. It grows during the game.

Mike B
  • 2,756
  • 2
  • 16
  • 28
  • 1
    `$(".blocks").each(function(){...});` would be more readable BUT now it really depends of what you mean by `Which way would be better`, better for what??? Performance? If so, use native js method instead. – A. Wolff May 05 '16 at 15:31
  • jsperf is down but I found this from [sitepoint](http://www.sitepoint.com/speed-question-jquery-each-vs-loop/) with screenshots from jsperf and some explanation. – bcr May 05 '16 at 15:31
  • 1
    Just to say what ever you are trying to do, surely you don't need to loop over all elements again and again. If you provide a more concrete sample of why would you need this, i'm sure there is better to do than looping each time over the complete list of elements – A. Wolff May 05 '16 at 15:36
  • Yes, I do. I have to check their data and create new element based on each one of them. – Mike B May 05 '16 at 15:39
  • Possible duplicate of [$.each() vs for() loop - and performance](http://stackoverflow.com/questions/11887450/each-vs-for-loop-and-performance) – Uyghur Lives Matter May 05 '16 at 17:57

3 Answers3

3

there are tons of performance tips in Javascript.

Please take a look here: What's the fastest way to loop through an array in JavaScript?

You will find very useful informations, but TL;DR here is the currently fastest loop that fits your case:

var blocks = document.getElementsByClassName("blocks");
for (var i=0, len = blocks.length; i<len; i++) {
    var val = blocks[i].textContent;
    ...
}
Community
  • 1
  • 1
Mattyyyy
  • 31
  • 4
  • Can you provide more details on how this advice applies in this particular case? – StriplingWarrior May 05 '16 at 15:40
  • Yes, but then he's doing an additional ID-selection inside of the loop, which would probably outweigh any performance gains he might get from using an iterator-based loop in the first place. – StriplingWarrior May 05 '16 at 15:42
  • You are right, but his question was which way he gains performance. However this gain is not as big, and "TL;DR" I posted the fastest way to loop an array. However this does not apply on all cases (e.g. browsers may have different JS Engine implementation) I'm editing the answer in order to fit the user case, thanks for this :) – Mattyyyy May 05 '16 at 15:48
  • Thanks for improving your answer. +1 – StriplingWarrior May 05 '16 at 15:51
1

I'm fairly certain that the cost of $("#block_"+i) will be high enough, compared with $(this), that it will offset any performance gains you'd get by using a more efficient for loop. This would probably be slightly more efficient:

var blocks = $(".blocks");
for(var i = 0, len < blocks.length; i++) {
      var val = $(blocks[i]).text();
      ...
});

However, quite certain that whatever else you're doing in your loop will be expensive enough that you won't see a significant improvement either way.

If performance is a concern here, I'd recommend you take a high-level approach to see if you can make any large-scale improvements on a design or algorithmic level. Otherwise, just use the code that's easiest to maintain.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • well, I can't improve the algorithm. But thanks. Finally an exact answer, that fits into my "super-broad" question. – Mike B May 05 '16 at 15:47
0

In general, your code should avoid using selectors and jQuery constructors when not needed. A more performant version of your code that constructs a set of elements only once would be something like:

// Save the reference to the entire collection; you'll need to update
// this as the list grows. You can use blocks.add() to add the newly
// created elements to the same set. It is _potentially_ faster than
// having to reselect the entire collection each time.
var blocks = $('.blocks', '#container');

// Iterate over each item using the callback function which
// receives the index number (0-indexed) and the actual
// HTMLElement in each iteraction
blocks.each(function(idx, item) {

  // `this` and `item` are the same thing in this case
  console.log(this === item);

  // `item` is an HTMLElement, it's not a wrapped jQuery object
  var text = item.textContent;

  // you can also get the jQuery item object by using the index;
  // this doesn't require you to construct a new jQuery object
  var $item = blocks.eq(idx);

  var value = $item.val();

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

The difference between this and your examples is that you don't have to keep reselecting and reconstructing objects, which is faster. There's no discernible difference between using a for() or $.each() in this case.

Klemen Slavič
  • 19,661
  • 3
  • 34
  • 43