What is this?

One of the most confusing aspects of jQuery is how it assigns scope during callbacks. It must be confusing because the topic generates a lot of questions on the mailing list. It's too bad, really, because jQuery sets the scope in order to simplify your code, not make it more confusing.

So here are some pointers that may help you remember what this is.

this is a DOM element

When is this a DOM element? The short answer is - usually. Scripting with jQuery quite often involves the use of callback functions. Whether handling an event, iterating a collection of nodes, animating an image, or applying a dynamic filter, callbacks are used to invoke your custom code at the appropriate time. To make things easy for you, jQuery sets the scope of the callback function to the element which is the subject of the callback. For example, when we want to handle a mouse click event for an element we bind a handler function to the event like so:

[js]$('#myButton').bind('click', function() { // our code to handle the click event goes // here, in the callback function });[/js]

When a user clicks the 'myButton' element, jQuery invokes the callback function that was passed to the bind method. But when it invokes our callback it sets the current scope to the DOM element that initiated the event, in this case the 'myButton' element. jQuery does this as a convenience. The object you are most likely to need in the event callback is the element that triggered the event. And what easier way to have access to it than by using the this keyword? So within the callback function it can be assumed that this is the relevant DOM element:

[js]$('#myButton').bind('click', function() { // 'this' is the DOM element that triggered the event alert(this.id == 'myButton'); });[/js]

Let's look at how often this is a DOM element when using jQuery. We just saw the case of an event handler; here are a few more:

Iterating elements with the each method:

[js]$('div').each(function() { // 'this' is a DOM element alert(this.tagName.toLowerCase() == 'div'); });[/js]

Using the load AJAX method:

[js]$('#myDiv').load('myUrl.php', function() { // this is the DOM element alert(this.id == 'myDiv'); });[/js]

Using animation:

[js]$('#myDiv').fadeOut('slow', function() { // this is the DOM element alert(this.id == 'myDiv'); });[/js]

Using selection filters:

[js]var set = $('div').filter(function() { // this is the DOM element alert(this.tagName.toLowerCase() == 'div'); return true; });[/js]

Using the "document ready" construct:

[js]$(document).ready(function() { // 'this' is the document object alert(this === document); });[/js]

Using global AJAX events:

[js]$().ajaxStart(function() { // 'this' is the document object alert(this === document); });[/js]

This last one may confuse you. Why is this the document object in the ajaxStart callback? The methods that wire your callbacks to the global AJAX events are binding methods. They bind your event handler to a DOM element. When the event occurs, your handler is called within the context of the DOM element(s). And when you use the dollar function with no arguments jQuery implicitly uses the document object as the selected element. So another way of writing the previous code snippet is:

[js]$(document).bind('ajaxStart', function() { alert(this == document); });[/js]

Now you can probably see how this is determined by how you call the AJAX binding methods:

[js]$(window).ajaxStart(function() { alert(this == window); }); $('#busyIndicator').ajaxStop(function() { alert(this.id == 'busyIndicator'); }); $('div.error').ajaxError(function() { alert(this.tagName.toLowerCase() == 'div'); });[/js]

this is an Object

I mentioned earlier that when iterating elements with jQuery's each iterator, this is always a DOM element. Technically, it is more accurate to say that within an each iteration, this is the subject of the current iteration loop. This distinction is important because jQuery's each method can be used to iterate over any array-like object, not just nodeLists.

[js]var arr = ['a','b','c']; $.each(arr, function(index, obj) { // 'this' is the object of the current iteration alert(this.constructor == String); alert(arr[index] == this); alert(this == obj); }); // or using a different but functionally equivalent syntax: $(arr).each(function(index, obj) { // 'this' is the object of the current iteration alert(this.constructor == String); alert(arr[index] == this); alert(this == obj); });[/js]

this is a jQuery Object

Plugin authors take note! If you've authored a plugin whose functionality can be applied to many elements, then you've most likely done so using the standard fn extension:

[js]$.fn.myPlugin = function() { // your plugin code goes here! });[/js]

Within your plugin function this is the jQuery object. And if you respect the Plugin Authoring Guidelines, your plugin method will always return this in order to maintain Chainability.

[js]$.fn.myPlugin = function() { // this is the jQuery object alert("jQuery version: " + this.jquery); return this; });[/js]

Typically, a plugin will operate on every DOM element that has been selected by the jQuery object. In a nutshell, this means using the each method within your plugin. You'll often find this technique implemented as follows:

[js]$.fn.myPlugin = function() { // this is the jQuery object alert("jQuery version: " + this.jquery); return this.each(function() { // this is now the DOM element that is // the subject of the 'each' iteration alert("current element: " + this.tagName); }); });[/js]

this is an AJAX settings Object

I talked earlier about about jQuery's load method and the global AJAX callbacks. Those callbacks are specifically bound to a DOM element or set of elements. The rest of the AJAX methods, $.get, $.post,$.ajax, etc, operate outside the context of a specific element set. But these methods can all be passed callback functions so it's important to understandwhat this is in those callbacks. Fortunately, all you need to remember is that for each of the local AJAX callback functions, beforeSend, success, complete, and error, this is always equal to the settings object used for the AJAX call.

[js]$.get('myUrl', function() { // 'this' is the AJAX settings object used by the get call alert(this.url == 'myUrl'); }); $.ajax({ type: 'POST', url: 'myUrl', timeout: 5000, beforeSend: function() { alert(this.url == 'myUrl'); }, error: function() { alert(this.timeout == 5000); }, success: function() { alert(this.type == 'POST'); }, complete: function() { alert(this.async == true); } });[/js]

Converting this to $this

When this is a DOM element it is often in the context of code that needs to access or manipulate it in some way. This, of course, is something that jQuery excels at. So how do we use the power of the jQuery API when this is a DOM element? Just turn this into $this:

[js]$('div').each(function() { // 'this' is a DOM element // wrap 'this' in a jQuery object var $this = $(this); // now we have the full jQuery API at our disposal var title = $this.attr("title"); if (title != null) $this.prepend("

" + title + "

"); });[/js]

When in Doubt

When you're confused about what this is within a given code block, ask yourself, "What makes the most sense here?" More often than not, the answer to that question is equal to this.



Responsive Menu
Add more content here...