Mar 11 2011

var self = this; huh?

Category: JavaScriptJon @ 4:40 am

This is a subject that comes up frequently on StackOverflow. Some questions approach it from seeing it in code but not understanding why, while others approach it from the opposite side — needing it but not knowing that they need it to solve their problem.

  • What is this?

    this is a context-sensitive variable. It is used to refer to the current context/object. It’s value or meaning depends on where and when it is used. Let’s look at a few, quick, examples.

    • On an element

      
      <input type="checkbox" id="chk_123" name="chk[]" value="123" onclick="alert(this.value;)" />
      

      Demo:
      <—- click me.

      In this case, this is the input element containing the code

    • In general functions

      
      function sayWindowName() {
        alert(this.name);
      }
      

      The above function will alert the value of window.name. General functions, like the one above, operate in the window context and this refers to the window object.

    • In constructor functions

      
      function Widget(name) {
        this.name = name;
      
        this.sayName = function() {
          alert(this.name);
        }
      }
      
      var bob = new Widget("Bob");
      alert(bob.name); //case 1
      bob.sayName(); //case 2
      setTimeout(bob.sayName,0); //case 3
      

      In the above, case 1 will open an alert dialog with “Bob”; case 2 will also open an alert dialog with “Bob”; case 3 will, however, open an alert dialog with nothing. For the first two cases, this is referring to the Widget object bob but not in the third case. We can make a small change and see what’s happening, though.

      
      window.name = "John";
      setTimeout(bob.sayName,0); //case 4
      

      Now, in the fourth case, we get an alert dialog with “John”. setTimeout is using the function from bob but in the window context. The same is also true for event listeners which is how the issue most often comes up.

  • Solving the problem for objects

    What we need is a way for methods to refer to their associated object without relying on a special variable like this whose value may change depending on how it is called.

    var self; to the rescue.

    Basically, we take advantage of variable scope to effectively cache the value of this. Let’s look again at the Widget above with the change.

    
    function Widget(name) {
      this.name = name;
      var self = this;
      this.sayName = function() {
        alert(self.name);  //note that here we use self instead of this.
      }
    }
    
    var bob = new Widget("Bob");
    alert(bob.name); //case 1
    bob.sayName(); //case 2
    setTimeout(bob.sayName,0); //case 3
    

    Now all three cases display the same behaviour, which is what we usually want. This is a very simple example but demonstrates the importance of understanding and taking advantage of variable scope.

    Also see previous, related, posts Prototype’s Bind and Curry and JavaScript Closures. I also recommend reading Richard Crockford’s article Javascript Closures as it is an extremely detailed look at that subject, and the execution context/scope issue specifically, in more detail than I have.

Leave a Reply