Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding some property to all selected items, which one is the right way and why?

Tags:

jquery

I am trying to understand the the correct way of coding.

My HTML

<div id="foo">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

If I want to add class bar to all the children divs of div foo, which way should I use?

Option 1 (turned out 3rd)

jQuery( '#foo > div' ).addClass( 'bar' );

Option 2 (turned out 4th fastest)

jQuery( '#foo' ).children( 'div' ).addClass( 'bar' );

Option 3 (turned out the fastest)

jQuery( '#foo' ).children( 'div' ).each(function(){
    jQuery( this ).addClass( 'bar' )
});

Option 4 (turned out very close 2nd)

jQuery( '#foo > div' ).each(function(){
    jQuery( this ).addClass( 'bar' )
});

These all accomplishes what I want. My Question is,

Which one should I prefer using over the other? Which cases should I use .each?

Edit with added snippet which shows using each is better than the other methords

var t0_start = performance.now();
$('#parent > div').addClass( 'bar' );
var t0_end = performance.now();

var t1_start = performance.now();
$('#parent').children('div').addClass( 'bar' );
var t1_end = performance.now();

var t2_start = performance.now();
$( '#foo > div' ).each(function(){
    $( this ).addClass( 'bar' )
});    
var t2_end = performance.now();

var t3_start = performance.now();
$( '#foo' ).children( 'div' ).each(function(){
    $( this ).addClass( 'bar' )
});    
var t3_end = performance.now();


outcome = 'selector: ' + (t0_end - t0_start);
outcome += "\n";
outcome += 'children(): ' + (t1_end - t1_start)
outcome += "\n";
outcome += 'selector: each(): ' + (t2_end - t2_start)
outcome += "\n";
outcome += 'children(): each(): ' + (t3_end - t3_start)
alert(outcome);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent"><div></div><div></div><div></div></div>

The result I got was time for selector: each() < time for children(): each() < time for selector: < time for selector: < time for children():

like image 693
rrk Avatar asked Jul 09 '15 14:07

rrk


People also ask

How do you add a property to an object?

One way is to add a property using the dot notation: obj. foo = 1; We added the foo property to the obj object above with value 1.

Which property allows you to add properties and methods to an object?

The prototype property allows you to add properties and methods to any object (Number, Boolean, String and Date etc.).

How can we add custom property to all instances of any object?

Using the prototype object to add custom methods to objects The prototype object can also help you quickly add a custom method to an object that is reflected on all instances of it. To do so, simply create the object method as usual, but when attaching it to the object (you guessed it), use "prototype" beforehand.


2 Answers

UPDATE: The perf tests seem to be getting optimized at runtime and providing some weird numbers. I've broken the tests into separate snippets (iframes) to get more consistent numbers.

UPDATE 2: Here's a jsbin wherein I attempt to gain some insight. The selector method is on average faster, but there's overlap. http://jsbin.com/jiluzu/edit?js,output

UPDATE 3: jsperf.com is back up! It further supports "selector" as the faster method. http://jsperf.com/jq-selector-vs-children

ORIGINAL: In this particular scenario I'd use the first example. It's more succinct and saves you an additional function call. Also, nowadays the "selector" method is more performant as well.

$('#parent > div');

var start = performance.now();
$('#parent > div');
var end = performance.now();

outcome = "$('#parent > div'): " + (end - start);
$('#parent').append(outcome);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent"><div></div><div></div><div></div></div>

$('#parent').children('div');

var start = performance.now();
$('#parent').children('div');
var end = performance.now();

outcome = "$('#parent').children('div'): " + (end - start);
$('#parent').append(outcome);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent"><div></div><div></div><div></div></div>

$('#foo > div').each()

var start = performance.now();
$('#foo > div').each(function(){});
var end = performance.now();

outcome = "$('#foo > div').each(): " + (end - start);
$('#parent').append(outcome);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent"><div></div><div></div><div></div></div>

$('#foo').children('div').each()

var start = performance.now();
$('#foo').children('div').each(function(){});
var end = performance.now();

outcome = "$('#foo').children('div').each(): " + (end - start);
$('#parent').append(outcome);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent"><div></div><div></div><div></div></div>

When to use each()

Using each is helpful in scenarios where you want to do some additional manipulations relative to each item selected.

For example, if we wanted to additionally add a class to the preceding element of each of the selected elements:

jQuery( '#foo' ).children( 'div' ).each(function(){
    jQuery( this ).addClass( 'bar' );
    jQuery( this ).prev().addClass( 'foo' );
});
like image 118
jthomas Avatar answered Oct 28 '22 22:10

jthomas


With jQuery, option 2 and 3 are probably quite similar, other than with each() you can perform more than one action per element in the selection using a function.

Option 1 is the least performant in older browsers like IE8, Chrome 5, Opera 9 with older versions of jQuery. This is because the CSS selector has to be parsed before making the actual selection, which is basically just going to call option 2 anyway.

Why you should never use CSS text selectors

$("#parent > .child"); and $("#parent .child"); both need to parse the selector and then just call: $('#parent').children().filter('.child') and $('#parent').filter('.child') respectively.

More info, including benchmarks for older browsers, here (from 2010).


The above is old news for modern browsers and jQuery. CSS selectors are faster nowadays.

like image 4
Inspector Squirrel Avatar answered Oct 28 '22 22:10

Inspector Squirrel