0

I am looking a better method than "find" to find all the elements within an element:

<table>
  <tr>
    <td class="test">
      Test
    </td>
  </tr>
  <tr>
    <td class="test">
      Test
    </td>
  </tr>
  <tr>
    <td class="test">
      Test
    </td>
  </tr>
</table>

This is structure and and I have jquery of table as $table

I am willing to do something like this:

$table.find('.test');

Find is a very expensive call. I need a better way to do it. I know I can do it with direct selectors like this:

$('table .test');

But I am looking for an alternative for find which performs better. Find performs really bad especially in IE.

emphaticsunshine
  • 3,725
  • 5
  • 32
  • 42

4 Answers4

3

The biggest thing you can do is to improve the selector you are using:

$table.find('td.test');

Providing an element name speeds up the selection significantly. This is especially true in versions of IE before IE9, which lack the getElementsByClassName method.

If you have getElementsByClassName, this won't offer a significant improvement. If you don't, however, the improvement will be massive. jQuery has to select every element that might match, then test to see if it has the relevant class present. If you provide td, it will only test td elements. If you don't, it has to test every element, which will obviously take much longer.

lonesomeday
  • 233,373
  • 50
  • 316
  • 318
1

find is slow in IE because IE does not implement a native getElementsByClassName. The fastest solution is apply knowledge of your DOM structure to the function that selects the elements. It is less flexible but always will be the fastest solution. In this case, it looks like the only elements that have the test class are td:

var rows = $table[0].rows, cells, i, j, numRows, numCells, result = [];
for(i = 0, numRows = rows.length; i<numRows; i++) { //Iterate over the table's rows
    cells = rows[i].children;
    for(j = 0, numCells = cells.length; j<numCells; j++) { //Iterate over the cells in the row
        if(cells[j].className == "test") { //Won't be valid if the cells have more than one class
            result.push(cells[j]);
        }
    }
}

This is just an example. Like I said, you sacrifice flexibility for speed, so you may need to tweak it to adapt to your particular structure but the principle remains.

Dennis
  • 32,200
  • 11
  • 64
  • 79
0

I think if you use

document.getElementById('myTable')

on

<table id="myTable">
  <tr>
    <td class="test">
      Test
    </td>
  </tr>
  <tr>
    <td class="test">
      Test
    </td>
  </tr>
  <tr>
    <td class="test">
      Test
    </td>
  </tr>
</table>

Will be fastest as possible.

T1000
  • 2,909
  • 7
  • 36
  • 53
-1

I made a jsperf to test $('.test', $('#my_table')) vs $('table .test');

http://jsperf.com/find-vs-direct

It looks like $('.test', $('#my_table')) is the winner

Mikey G
  • 3,473
  • 1
  • 22
  • 27
  • 1
    That is a pointless case, in one you are using the `id` the other you are just using `table`. `id` will always out perform `table`. And more importantly, you don't have anything with that ID, so you're getting back nothing. – James Montagne Feb 03 '12 at 22:04
  • This is less true (in fact, completely false) if [you do a fair comparison](http://jsperf.com/find-vs-direct/4). – lonesomeday Feb 03 '12 at 22:05
  • dude... there is no $("#my_table") so it will obviously perform better...try now – emphaticsunshine Feb 03 '12 at 22:06
  • lol thanks, i guess you're right, i fixed that now. And i don't see how it's pointless because i wouldn't call that common knowledge – Mikey G Feb 03 '12 at 22:09