Understanding the 'this' keyword in javaScript and JQuery - $(this)

This in C#, Java, C++

The keyword this is something that has special meaning for most developers that have worked with the C family of object-oriented languages (i.e. Java, C++, C#).  In those languages the keyword this is used by the containing class's instance to refer to itself.  Depending on the conventions and standards used, many of us do not use the keyword even though we know it's there.  That is because, as an example, in C# many developers use naming conventions that eliminate any need for it.  In a popular C# convention, for example, a property always starts with an uppercase character, a non-public field starts with an underscore and  local variables start with lower case characters.

Therefore according to that convention the following statements hold true:

  • _age is a field
  • age is a local variable
  • Age is a property

In those languages this is only necessary to express the scope and that is usually only when you have other variables that might obscure a field or property by the same name.  For instance, you may have  the following class defined in the following style(which I've noticed to be a common style in Java).

public class Foo
{
     private int bar = 1;


     private void SetBar(int bar)
     {
         this.bar = bar;
     }
}


In the code above, it is necessary to use the keyword this to differentiate between the class level scope and the local scope of bar.  The reason is that the local variable bar hides the class variable (or field) and therefore it is necessary to use this to precede it in order to express class-level scope.


This in javaScript


Javascript, being a whole different language, follows different rules for the keyword this.  As seen in the example above, the keyword this within that method always refers to current instance of Foo and nothing else - Ever!  In javascript there is a whole different story for the keyword this.  The keyword this depends on the context in which it is used.   That has a lot to do with the fact that in javaScript functions are first class objects/classes/citizens.  Therefore, depending on the context set, this can take on a different meaning each time.  I will cover this in detail later, for now just keep that in mind.


Why this Why Now


What prompted me to write this post was because my latest challenge required me to understand the keyword this and I could not find a good description anywhere (on the web). I was faced with a challenge that required me to determine which element in the document object model (DOM) had been clicked.  I was working on creating a daily log for my website: http://followmetotheweb.apphb.com/DailyLog.html. I wanted to play around with the concept of outlining all my daily entries, but only displaying the details of each entry at the users leisure.  This could be done by clicking the "...see more" link, similar to what you do when you subscribe to blogs through RSS feeds and such.

The Challenge

That sounds really easy on the surface.  One idea is to simply create a div give it an ID and then using jQuery, simply call show() and hide().   That works fine but I wanted to reuse my javaScript code because I did not want to give each entry a unique ID.  That way I could re-use my code for each and every entry.  That meant, to me anyways, that a better solution would be to use classes - classes from the perspective of CSS styling and not of object-oriented programming.  That is because classes can be applied to multiple elements within the DOM whereas IDs cannot.

So this revealed a challenge. In order to reuse the code, I needed to know which element was clicked so that I would only select those elements relative to the element that was clicked.  In other words, it would not be correct to show all entries and hide all entries upon clicking the "see more" link.  Instead I wanted to show and hide those entries relative to that "see more" link.

Enter the keyword this. This would allow me to determine which element was clicked and then using jQuery I could navigate the relatives within the tree and show or hide the appropriate div.  That would leave all the other hidden entries, which also could be shown and hidden, but not relative to this particular "see more" link, in their current state.

I went on to implement my code but couldn't get the jQuery call to $(this) to bring back the correct element.  The problem was that I was not setting the context.

So I had the following method:


                var checkIfIsExpanded = function(){
                               
                    if(  $(this)
                         .parents(".log_entry")
                         .children(".popup_details")
                         .is('.expanded') )
                    {
                            return true;
                    }
                     
                    return false;    
                }

Which was called from the following callback


                   $(".show_popup").click(function(){  
                    
                       isExpanded = checkIfIsExpanded();
                    
                       if(isExpanded == false)
                       {
                           //load popup  
                           loadPopup();
                       }
                       else
                       {
                           disablePopup();
                       }
                   });


Setting the this Context

For whatever reason this was not working.  I had a bit of a hard time finding the exact description of how the keyword this works, after various searches on the internet.  However, I did find a good explanation on the book jQuery IN ACTION


What I discovered is, that when the functions are called the way I called them above, as top-level functions, the keyword this represents the Window object.   So what I did instead was this:


                                   $(".show_popup").click(function(){  
                    
                    isExpanded = checkIfIsExpanded.call(this);
                    
                    if(isExpanded == false)
                    {
                        //load popup  
                        loadPopup.call(this);
                        setExpandedClass.call(this);
                    }
                    else
                    {
                        disablePopup.call(this);
                        removeExpandedClass.call(this);
                    }
                });



By using the invocation call on my functions instead of calling them as top-level functions, I was able to set the context of this to element with the class ".show_popup".  That is because when you use the call() function, the first parameter sets the context.  In my case that was the query element setting the callback - $(".show_popup"). This set the context of this for all the functions that I was calling.  By doing this, I was able to navigate the DOM in relation to the element that was clicked.  Where the loadPopup() function would simply look like the one below.  Because I was setting the context when called, my functions knew what this was and then could navigate the DOM in relation to that element.  For example the code below navigates to an anchor that has class set "show_popup".  That element is nested within a div that has a class named ".log_entry".  The element, or div, within the class ".log_entry" has a child that has all the hidden details that can be expanded or compressed on demand.  All these elements don't necessary carry a direct child or direct sibling.  However they are contained with the log_entry div and as such we can limit our search for them to that parent element.

                //loading popup   
                var loadPopup = function(){  
                    //loads popup only if it is disabled  
                    if(isExpanded === false){  
                    
                        $(this)
                         .parents(".log_entry")
                         .children(".popup_details")
                         .fadeIn("slow");
                    }  
                }



Summary

The keyword this is not only useful in JavaScript, but necessary.  Using the keyword this allowed me to re-use my code so that I did not have to query for each individual element.  Instead I used this to provide me with my current location.  From there I was able to navigate the relative DOM and show and hide my targeted elements.

To see the full code just navigate to http://followmetotheweb.apphb.com/DailyLog.html.  Take a look at the daily entry for 9/25/2011.  You can right click and view the source - everything to include the javascript is visible. Just look for the "see more" link to expand or compress entries within that page.

I hope this helps you get a better understanding of this as it pertains to jQuery and JavaScript.

As usual, please let me know if you like this article, or if you didn't, if it was helpful or if it wasn't.  I appreciate every one's feedback and thank you in advance for leaving me feedback.



Comments

Fernando Zamora said…
And then I found this... I could probably use the :visible technique for this article we''ll see
http://www.webgeekly.com/tutorials/create-a-simple-jquery-drop-down-menu-in-3-simple-steps/
Fernando Zamora said…
I've since found a better explanation that what I have. Take a look at http://unschooled.org/2012/03/understanding-javascript-this/

Popular posts from this blog

Simple Example of Using Pipes with C#

Putting Files on the Rackspace File Cloud

Why I Hate Regular Expressions