views:

394

answers:

5

Possible Duplicate:
jQuery $(this) vs this

In jquery sometimes I find that within a function I have to use $(this) because this won't work:

var listItems = $('li');
listItems.each(function(index) {
    $(this).css({ 

    })
})

Any ideas as to the reason why?

+20  A: 
  • $() is the jQuery constructor function
  • this is a reference to the DOM element of invocation

So basically, you're turning a DOM reference into a jQuery object

In your example, you could also use

listItems.each(function(index, element){
   $(element).css({
   });
});

..since .each() will pass both, index + element in it's callback.

jAndy
Brilliant. I understand fully. Thanks guys
elduderino
+6  A: 

this is the native DOM element. $(this) is a jQuery object that allows you to call functions such as .css() on it.

Darin Dimitrov
+3  A: 

this is typically a DOM object by default, which means it only has the methods on normal DOM objects.

If you want to invoke a library-specific function (such as jQuery's .css function), you have to convert it to a full jQuery object first, which is what $() does by default if you pass it a DOM object.

(You can also pass other things to $(), such as an HTML string (to construct a new jQuery-wrapped DOM object) or a CSS selector (to get a set of jQuery objects that correspond to DOM objects matching the selector).

Amber
+3  A: 

I know I'm a bit late to this thread but I just wanted to bring up the fact that redundant wrapping of DOM objects is one of the most frequently committed crimes against jQuery. Taking care with your jQuery-instance constructing can have tremendous effects performance-wise and it's so easy to do that you have no excuse not to.

Typically, when people have a DOM object (whether it be referenced as this or element) they'll try to wrap it each time they need access to a jQuery method:

jQuery(this).css('a', 'b');

The problem is when you're doing this multiple times:

jQuery(this).css('a', 'b');
jQuery(this).find('span').attr(...);
jQuery(this)....

Every time jQuery() is called, a new jQuery instance is constructed. That kind of operation is expensive and should be avoided if at all possible -- especially in loops!

To avoid this, for one, you could utilise chaining with all methods that return a jQuery instance $(this).css(a,b).attr(a,b)...). The rest of the time you should have a locally declared variable that refers to the jQuery instance and then just use that:

var self = jQuery(this);
self.css(...);
self.attr(...);

If you're doing this within an .each() callback function, there is still a new jQuery object being constructed on every single iteration. You can avoid this by having one generic jQuery object which you continually mutate and then you can run jQuery methods off that single instance:

Look at this:

jQuery.single = function(a){
    return function(b){
        a[0] = b;
        return a
    }
}(jQuery([1]));

Now look at this:

$('a').each(function(i){
    $.single(this).append('Anchor number ' + i);
});

Only one jQuery object is being used. You can make it even faster by avoiding the identifier resolution:

$_ = $.single;
$('a').each(function(i){
    $_(this).append('Anchor number ' + i);
});

Food for thought. More info here: http://james.padolsey.com/javascript/76-bytes-for-faster-jquery/

J-P
@J-P: interesting approach. One comment said something about a possible memory leak there, was that approved / disproved ?
jAndy
Hi J-P, Great post. I just don't understand the last bit. What's identifier resolution? Also on reading the article and the comments it does seem there are a few issues with this approach (memory leak, conflicting with the bind method), but all in all it's made me very aware of how jquery instances I invoke in my code.
elduderino
+1  A: 

If you are using Firefox, try console.log($(this)) and console.log(this) to see the difference.

romanEgloo