What is this?

read 33 comments

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:

JavaScript:
  1. $('#myButton').bind('click', function() {
  2.     // our code to handle the click event goes
  3.     // here, in the callback function
  4. });

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:

JavaScript:
  1. $('#myButton').bind('click', function() {
  2.     // 'this' is the DOM element that triggered the event
  3.     alert(this.id == 'myButton');
  4. });

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:

JavaScript:
  1. $('div').each(function() {
  2.     // 'this' is a DOM element
  3.     alert(this.tagName.toLowerCase() == 'div');
  4. });

Using the load AJAX method:

JavaScript:
  1. $('#myDiv').load('myUrl.php', function() {
  2.     // this is the DOM element
  3.     alert(this.id == 'myDiv');
  4. });

Using animation:

JavaScript:
  1. $('#myDiv').fadeOut('slow', function() {
  2.     // this is the DOM element
  3.     alert(this.id == 'myDiv');
  4. });

Using selection filters:

JavaScript:
  1. var set = $('div').filter(function() {
  2.     // this is the DOM element
  3.     alert(this.tagName.toLowerCase() == 'div');
  4.     return true;
  5. });

Using the "document ready" construct:

JavaScript:
  1. $(document).ready(function() {
  2.     // 'this' is the document object
  3.     alert(this === document);
  4. });

Using global AJAX events:

JavaScript:
  1. $().ajaxStart(function() {
  2.     // 'this' is the document object
  3.     alert(this === document);
  4. });

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:

JavaScript:
  1. $(document).bind('ajaxStart', function() {
  2.     alert(this == document);
  3. });

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

JavaScript:
  1. $(window).ajaxStart(function() {
  2.     alert(this == window);
  3. });
  4. $('#busyIndicator').ajaxStop(function() {
  5.     alert(this.id == 'busyIndicator');
  6. });
  7. $('div.error').ajaxError(function() {
  8.     alert(this.tagName.toLowerCase() == 'div');
  9. });

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.

JavaScript:
  1. var arr = ['a','b','c'];
  2. $.each(arr, function(index, obj) {
  3.     // 'this' is the object of the current iteration
  4.     alert(this.constructor == String);
  5.     alert(arr[index] == this);
  6.     alert(this == obj);
  7. });
  8. // or using a different but functionally equivalent syntax:
  9. $(arr).each(function(index, obj) {
  10.     // 'this' is the object of the current iteration
  11.     alert(this.constructor == String);
  12.     alert(arr[index] == this);
  13.     alert(this == obj);
  14. });

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:

JavaScript:
  1. $.fn.myPlugin = function() {
  2.     // your plugin code goes here!
  3. });

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.

JavaScript:
  1. $.fn.myPlugin = function() {
  2.     // this is the jQuery object
  3.     alert("jQuery version: " + this.jquery);
  4.     return this;
  5. });

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:

JavaScript:
  1. $.fn.myPlugin = function() {
  2.     // this is the jQuery object
  3.     alert("jQuery version: " + this.jquery);
  4.     return this.each(function() {
  5.         // this is now the DOM element that is
  6.         // the subject of the 'each' iteration
  7.         alert("current element: " + this.tagName);
  8.     });
  9. });

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.

JavaScript:
  1. $.get('myUrl', function() {
  2.     // 'this' is the AJAX settings object used by the get call
  3.     alert(this.url == 'myUrl');
  4. });
  5.     type:   'POST',
  6.     url:    'myUrl',
  7.     timeout: 5000,
  8.     beforeSend:  function() {
  9.         alert(this.url == 'myUrl');
  10.     },
  11.     error: function() {
  12.         alert(this.timeout == 5000);
  13.     },
  14.     success:  function() {
  15.         alert(this.type == 'POST');
  16.     },
  17.     complete:  function() {
  18.         alert(this.async == true);
  19.     }
  20. });

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:

JavaScript:
  1. $('div').each(function() {
  2.     // 'this' is a DOM element
  3.     // wrap 'this' in a jQuery object
  4.     var $this = $(this);
  5.     // now we have the full jQuery API at our disposal
  6.     var title = $this.attr("title");
  7.     if (title != null)
  8.         $this.prepend("<h2>" + title + "</h2>");
  9. });

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.



comment feed

33 comments

  1. Excelent, excelent, excelent post. 'This' is great for begginers like me :)
    Thanks!

  2. Aha - that came a fraction too late for me. I ended up writing a blogpost about my discovery of what this means, and where, which I found out the hard way. Still, this article looks great too - thanks for being so comprehensive.

  3. Bill Warters

    Hi there. I got interested in trying out jQuery after seeing your session at the Grandrapids BarCamp. Right now, however, I'm stumped trying to get my selectors straight...I guess this is just not what it seems.

    Briefly, I've got a blog setup I'm building that I'd like to add an "Add to favorites" feature to. I can submit the query and get back the data string I'm looking for, but I can't figure out how to select the span that my trigger link resides within so that I can replace it's html with the returned data.

    Sample blog html snippet

    <h2>A Sample Posting to the Blog</h2>
    <p class="postedby">Posted by <a href="/forums/member/1/">Fred</a> on Aug 03, 2007  
    <span class="favorites_span" id="favorite_1750">
    <a class="Favorites_Trigger" id="1750" href="/forms/favorite-add/1750">Add to favorites?</a>
    </span>
    </p>
    <p>Here is a sample posting in the blog. This could be written by an expert in the area.
    </p>

    And here's the bit of Jquery code that I can't quite get to replace my favorites span contents.

    <script type="text/javascript" src="includes/jquery"></script>
    <script type="text/javascript">
    $().ready(function() {
    $('a.Favorites_Trigger') .click (function() {
    var itemid = this.id;
    $.get(this.href, function(data) {
    var myresponse = data;
    var spanid = "favorite_" + itemid;
    alert(data);
    });
    return false;
    });
    });
    </script>

    Should I be trying to get the parent of my trigger link, and if so, how do I get there from "this"?
    As you can see, I can even construct the unique span id I'm looking for based on the link id, but my javascript skills are not up to the task of using this variable correctly in a jquery select statement.
    Any help would be much appreciated...

  4. Bill Warters

    Oops, I thought Karl posted this...I don't recall Mike being at BarCamp GrandRapids.

  5. Bill Warters

    Got it sorted...Here's the selector I needed, placed in the code where the alert now sits.

    $("span#"+spanid+".favorites_span").html(data);

  6. Like Bill, I'm also having trouble combining this and/or $(this) with selectors. A future blog post exploring this topic would be greatly appreciated for us beginners! :-)

  7. Jeroen, $this is just a naming convention used by many jQuery developers. It helps you remember that the variable is a jQuery object rather than a DOM element (assuming you're following the convention). For example:

    $('#myButton').click(function() {
    // in the event handler 'this' is a DOM element
    alert (this.id == 'myButton');

    // wrap this in a jQuery object so we can use the jQuery API
    var $this = $(this);

    // now we have this and $this to play with
    alert( $this.attr('id') == 'myButton');
    });

  8. Tyson

    When you call Jquery from within function in a custom Javascript class, how do you refer to the containing object in the Jquery callback function since Jquery uses "this" to refer to the DOM object in the callback function?

  9. Carter

    Tyson (and anyone else searching this),
    This is how I've been doing it:

    $(".button").bind("click", {that:this}, function(event) {
          var that = event.data.that;
          that.handleEvent();
          return false;
    });

    If you pass in an object after the binding event type arg ("click") it get's tacked onto the event's "data" property. I've been looking for a nicer way to do this... just posted in the google groups forum. Prototype has a bindAsEventListener method that you can tack onto any function to let you say what you want "this" to reference inside the function.

    Hope this helps,
    Carter

  10. @Tyson: You just need to create a closure to capture the object you need to reference in the callback. For example:

    ...
    var self = this;
    $('#myElement').click(function() {
    // here you can use 'self' to reference
    // the enclosing object
    });
    ...

  11. hello , i am trying to use the jQuery load() function , i am using it like this $("#mydiv").load("myfile.php?argument=x");
    all works fine untill i want to process the results returned by the function , meaning that the file myfile.php prints some parts of an form based on some arguments received , the problem is that when i want to process the values of the form elements i cannot because it hasn't generated any html code for them , you can see the problem at http://www.potirnel.8k.ro/formular2/ , any help is great. potirnel@yahoo.com

  12. how do i get the received content of the ajax-/get-function to the div element again ?

    thanks...
    raimund

  13. Brijesh Kumar Sharma

    your live comment preview is meaning less. why are you giving fullish type of live comment.
    when we type then we can see what i type.

  14. Brijesh Kumar Sharma

    what the hell u r doing in coding. how i know that my comment is saved. no any message prompt.

  15. This is sweet and so so helpful.

    Regarding the solution in #10 (which worked perfectly) - is there no other way to bind than this solution? It works but seems inelegant... I wish I could just bind on the function somehow. Ah well! Thanks for this very useful post

  16. iDVB

    Hey Mike,
    Great article btw.

    In your "AJAX settings Object" example...what if I'm making a $.ajax() call inside a method of an object (myObject) and I want to access that myObject from within the "success" of that ajax callback?

    I tried this.methods but it (this) is of course the options of the ajax call....I also tried setting a property within the myObject like so...
    var self = this;
    and then tried to use that from within the ajax callback like so:
    self.methods
    and success! BUT!

    now I have two separate objects doing this ...myObject1 and myObject2
    and now by the time myObject2's ajax callback runs ... self now equals myObject1!!!???

    HELP! I'm all scoped out :P

    • Don't know if you sorted this one out, but you can solve it by wrapping your callback call in an anonymous function. Like so:

      
      var obj = this;		// Workaround for jQuery's assignment of this in ajax callback
      
      $.ajax({
      url:		"ajax/ajx_load.php",
      success:	function(data) {
      // In this scoope this refers to the ajax settings object. Arghhh! Not what we want.
      
      obj.load_query_cb(data);  // Problem solved! The mecanism we rely on is calld scoop chaining, I think.
      
      },
      data:		post_data,
      type:		'POST'
      });
      
      

      The code is from a method of my object. load_qeury_cb() is a method of the same object. Now the ajax call works in my OOP code.

  17. Chris

    Thanks! Very helpful.

  18. get a new code highlighter.

  19. mabed

    The code in all the articles on your site is unreadable. Is there anything I can do to get rid of the named entities? I've tried 4 browsers already! Is this something wrong with your site.

  20. Scoping is one of the most annoying part of javascript and jQuery. Working OOP, you never want this to be anything else than the class you are in.

    in YUIs eventhandling, you can send the scope to the eventHandler to prevent the confusion. It would be great to have a OOP layer over jQuery that won't manipulate this the same way jQuery does by over-using fn.apply() and fn.call().

    Consider this:

    var myOwnScope = {
        secret : 'Nobody knows what I am'
    };
    
    jQuery.fn.addEventListener = function(type, fn) {
        $(this).bind(type, function(e) {
            fn.call(myOwnScope, e);
        })
    }
    
    $('input').addEventListener('click', function(e) {
        console.log(this);
    })
    

    What is this? it's impossible to tell in javascript event handling. I just wished jQuery would take care of that, just as actionscript 3 took care of it from AS2, which suffered the same scoping problems as javscript has.

  21. Aninda Sen

    great article! I am having two problems with jQuery and classic asp. I am trying to make a callback from one asp page jquery to server code in a different asp page. In that other page I am trying to fetch from the database but getting error on Server.CreateObject("ADODB.Command") line. Why can't I create ADO object in the callback function. Is it something that I am doing wrong? Also when I do a return false from within the jquery ajax call it is ignoring the return false statement and going ahead and executing the succeeding code. How can I stop that?

  22. sanza702

    Hi,

    I'm pulling out data from my database and displaying this on my webpage, thing is, I'm fairly new at this and I'd like to be able to toggle each table of data which is separated by entry in the database on its own. The layout of the page is as follows:

    User:
    details of that user in a table hidded in a panel:
    &lt div class"panel" &gt
    &lt table &gt table here &lt /table &gt
    &lt /div &gt

    &lt p class="flip" &gt Click to view users' details &lt /p &gt

    Since this happens iteratively, we end up with as many panel/tables as there are entries, but when I click on one of the panels, all get expanded obviously because they all share the same class name, below is how the javascript bit looks like, can you please assist in this regard?

    $(document).ready(function(){
    $(".flip").click(function(){ $(".panel").slideToggle("slow"); });
    });

    How do I change this such that only one panel gets to be expanded?

  23. mitul

    You can visit this really good one..

    Your text to link...

  24. thenboo

    So wonderful! So great! So cool this tutorial!

    Can't thank you so much!

  25. squirtle23

    Aha! I think I am so late in reading this... but I just recently learned Jquery coming from SWT Desktop Apps (Boo!)... So Great tutorial! I had trouble understanding this keyword! But this blog simplifies eveything!

    I must say, I am a fan of Mike Alsup.. Been using the form plugin/cycle/media plugin in my site... Dont know how to thank him

    --Squirtle23

  26. it would be cool to see these examples written with all of the updated methods - .bind is used, but is far from current as of 1.4.4 & 1.5.
    there is so much extended functionality with callbacks (.live(), .delegate())
    Thanks!

  27. Darryl

    {start rant}

    Does anybody think that "this" is screwed up? I do.

    Writing syntax that is entirely context dependent opens the doors for countless errors. What irritates me the most is that HTML5/JavaScript is the future. The move is towards replacing apps with hard to maintain, cryptic apps based on JavaScript. Those who think that Flash is irritating enough, just wait until they run up against JavaScript.

    Anyway, I don't wish to turn this into a thin-client/ fat-client debate or an html5 vs flash debate. It is pointless. The writing is on the wall: javascript is the future, we just have to put up with its annoying quirks.

    I just want to make something clear: I have no complaints whatsoever about JQuery.

    {end of the rant}

7 Pings

  1. [...] of the new image to 0 so that we can fade it in using the animate() function. Finally, we attach a callback to remove the z-index classes from the previous image when animate() [...]

  2. [...] of the new image to 0 so that we can fade it in using the animate() function. Finally, we attach a callback to remove the z-index classes from the previous image when animate() completes. Which is all [...]

  3. [...] can be quite confusing. Mike Alsup does a pretty good job of explaining what “this” is here. Rather than trying to explain exactly what “return”, “this”, and [...]

  4. [...] of the new image to 0 so that we can fade it in using the animate() function. Finally, we attach a callback to remove the z-index classes from the previous image when animate() [...]

  5. [...] of the new image to 0 so that we can fade it in using the animate() function. Finally, we attach a callback to remove the z-index classes from the previous image when animate() [...]

  6. [...] this documentation, whereas with jQuery I've come across little that's more understandable than the what is this piece from the Learning jQuery site. __________________ Programming Group Advisor Reference: [...]

  7. [...] object to a function. I did this so I could refer to each object matching the selector as “this“. There might be a way to do this manipulation without “this”, but [...]

Sorry, but comments for this entry are now closed.


Advertise on our network
See our other websites