views:

66

answers:

3

jQuery is currently providing me with a fun introduction to Javascript after 12 years of surviving happily without. I'm at the stage where I'm trying to learn as much as I can about optimising the code I write and, whilst I have found plenty of good reference material, there is something quite basic which is puzzling me and I have been unable to find anything about it anywhere.

When I'm attaching something to an element how should I be referring to that element within the function. For example, when attaching a function to an element's click event :

$('#a_button',$('#a_list_of_buttons')).click(function() {
    // NOW WHAT'S THE BEST WAY TO REFER TO '#a_button' ?
});

I know not to keep re-selecting it like so as the browser has to search the whole DOM again from scratch to find what it's already found once :

$('#a_button').click(function() {
    // I KNOW THAT THIS IS NAUGHTY
    var buttonValue = $('#a_button').val();
    $('#a_button').addClass('button_has_been_clicked');

});

Currently I'm using either of the following but am not entirely sure what each is actually doing :

$('#a_button').click(function() {
    // USING this
    var buttonValue = $(this).val();
    $(this).addClass('button_has_been_clicked');
});

But is this just re-selecting like in the first "naughty" example?

$('#a_button').click(function(event) {
    // USING event.target
    var buttonValue = $(event.target).val();
    $(event.target).addClass('button_has_been_clicked');
});

This seems like it might be better but is it efficient to refer to 'event.target' multiple times?

$('#a_button').click(function(event) {
    // USING A LOCAL VARIABLE
    var thisButton = $(this);

    // OR SHOULD THAT BE
    var thisButton = $(event.target);

    var buttonValue = thisButton.val();
    thisButton.addClass('button_has_been_clicked');
});

I understand the performance efficiencies of passing things to variables but I'm unsure whether or not in these situations using $(this) or $(event.target) provides me with the same efficiencies already and so by setting a new variable I'm actually doing more work that I need to.

Thank you.

+2  A: 

I may be wrong, but this and event.target are both just different references to the same element.

this and event.target are not always references to the same element. But in answer to your question, var thisButton = $(this); is definitely the winner. If you were writing C# code, you would never do the following:

this.Controls[0].Controls[0].Text = "Foo";
this.Controls[0].Controls[0].Controls.Clear();

You would do this:

var control = this.Controls[0].Controls[0];

So you probably should never re-use $(this) more than once either. Althought it's trivial to convert this from a DOM element to a jQuery object, it's still an unnecessary overhead.

However, sometimes you need to gear back from optimisation to make sure your code maintains it's readability.

Another option of course is just to change what this is. This is javascript afteral:

this = $(this); // Now `this` is your jQuery object

Disclaimer: I only just tried the above and it seemed to work. Might have some issues though.

GenericTypeTea
The `target` property of event objects is normalized in jQuery and will work the same in all browsers that it supports. It isn't always the same as `this`.
Tim Down
@GenericTypeTea - your winning method is what I've seen in pretty much all of the reference material I've read but no-where did it explain why they used this method, other than that using the equivalent of $('#a_button') should be avoided as it requires a fresh DOM lookup whenever it's used.
Chris Stevenson
@Tim - updated the answer. Thanks.
GenericTypeTea
@Chris - It's the winning solution because of exactly what you said. It stops an unneccessary DOM lookup. Once you've assigned the value from the DOM once, you've got the jQuery object it until it goes out of scope.
GenericTypeTea
@GenericTypeTea - Your answer makes perfect sense to me but I'm now confused as the answers from @Wallace Breza and @Baju seem to suggest that $(this) and $(event.target) are performing the same job in this situation as a locally set variable would, ie an overhead-free reference to the element that I can re-use without penalty whilst it's still within scope.
Chris Stevenson
@GenericTypeTea - ... and I fully agree with your comment about a balance between optimising for performance and optimising for readability/maintainability, I'm just trying to learn as much as I can so that I can achieve the best balance I know how to.
Chris Stevenson
@Chris - Baju has correctly pointed out that `event.target` is not always the same as `this`. I also updated my answer a while ago when Tim Down said I was wrong. `event.target` can also be the child control that is bubbling the event up to `this`.
GenericTypeTea
A: 

In my experience i would go with the following:

$('#a_button').click(function() {
    // USING this
    var buttonValue = $(this).val();
    $(this).addClass('button_has_been_clicked');
});

The this in the context of your click callback method is a reference to the DOM event. Since you already have a reference to the DOM object it is trival to convert it into a jQuery object since a lookup is not required.

But on a side note, if you don't need to use jQuery in your callback, then don't. You can simply get the value of the button using standard JS this.currentTarget.value.

The other examples you mentioned require a DOM lookup, and depending on the complexity of your selector can take longer. Using a id based lookup like '#a_button' will perform better than a class based looked like .myClass.

Wallace Breza
@Wallace Breza - Just to clarify then, does using 'event.target' require an additional DOM lookup? Oh, and learning about the standard Javascript for some of the jQuery stuff is definitely on my list of things to do so thanks for the note.
Chris Stevenson
@Chris Stevenson - No, event.target already contains the DOM element that raised the event and does not require an additional lookup. So `$(this)` would be the same as `$(event.target)` in your examples.
Wallace Breza
+1  A: 

this and event.target are not always the same. this refers to the element you assigned the listener to ( in this case the '#a_button' ). event.target however is the element that actualy triggered the event, which can be a childnode of #a_button.

So $(this) is the thing you are looking for.

See reference: http://api.jquery.com/event.target/

Baju
@Baju - It's precisely the situations where 'this' and 'event.target' are the same that are causing the confusion for me.
Chris Stevenson