Maxim Gershkovich Maxim Gershkovich - 1 month ago 11
Javascript Question

How does the "this" keyword work?

I have noticed that there doesn't appear to be a clear explanation of what the

this
keyword is and how it is correctly (and incorrectly) used in JavaScript on the Stack Overflow site.

I have witnessed some very strange behaviour with it and have failed to understand why it has occurred.

How does
this
work and when should it be used?

Answer

I recommend reading Mike West's article Scope in JavaScript (mirror) first. It is an excellent, friendly introduction to the concepts of this and scope chains in JavaScript.

Once you start getting used to this, the rules are actually pretty simple. The ECMAScript Standard defines this as a keyword that "evaluates to the value of the ThisBinding of the current execution context" (§11.1.1). ThisBinding is something that the JavaScript interpreter maintains as it evaluates JavaScript code, like a special CPU register which holds a reference to an object. The interpreter updates the ThisBinding whenever establishing an execution context in one of only three different cases:

  1. Initial global execution context

    This is the case for JavaScript code that is evaluated when a <script> element is encountered:

    <script type="text/javascript">//<![CDATA[
    alert("I'm evaluated in the initial global execution context!");
    
    setTimeout(function () {
        alert("I'm NOT evaluated in the initial global execution context.");
    }, 1);
    //]]></script>
    

    When evaluating code in the initial global execution context, ThisBinding is set to the global object, window (§10.4.1.1).

  2. Entering eval code

    • ... by a direct call to eval()

      ThisBinding is left unchanged; it is the same value as the ThisBinding of the calling execution context (§10.4.2(2)(a)).

    • ... if not by a direct call to eval()

      ThisBinding is set to the global object as if executing in the initial global execution context (§10.4.2(1)).

    §15.1.2.1.1 defines what a direct call to eval() is. Basically, eval(...) is a direct call whereas something like (0, eval)(...) or var indirectEval = eval; indirectEval(...); is an indirect call to eval(). See chuckj's answer to (1,eval)('this') vs eval('this') in JavaScript? and this blog post by Dmitry Soshnikov for when you might use an indirect eval() call.

  3. Entering function code

    This occurs when calling a function. If a function is called on an object, such as in obj.myMethod() or the equivalent obj["myMethod"](), then ThisBinding is set to the object (obj in the example; §13.2.1). In most other cases, ThisBinding is set to the global object (§10.4.3).

    The reason for writing "in most other cases" is because there are eight ECMAScript 5 built-in functions that allow ThisBinding to be specified in the arguments list. These special functions take a so-called thisArg which becomes the ThisBinding when calling the function (§10.4.3).

    These special built-in functions are:

    • Function.prototype.apply( thisArg, argArray )
    • Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
    • Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
    • Array.prototype.every( callbackfn [ , thisArg ] )
    • Array.prototype.some( callbackfn [ , thisArg ] )
    • Array.prototype.forEach( callbackfn [ , thisArg ] )
    • Array.prototype.map( callbackfn [ , thisArg ] )
    • Array.prototype.filter( callbackfn [ , thisArg ] )


    In the case of the Function.prototype functions, they are called on a function object, but rather than setting ThisBinding to the function object, ThisBinding is set to the thisArg.

    In the case of the Array.prototype functions, the given callbackfn is called in an execution context where ThisBinding is set to thisArg if supplied; otherwise, to the global object.

Those are the rules for plain JavaScript. When you begin using JavaScript libraries (e.g. jQuery), you may find that certain library functions manipulate the value of this. The developers of those JavaScript libraries do this because it tends to support the most common use cases, and users of the library typically find this behavior to be more convenient. When passing callback functions referencing this to library functions, you should refer to the documentation for any guarantees about what the value of this is when the function is called.

If you are wondering how a JavaScript library manipulates the value of this, the library is simply using one of the built-in JavaScript functions accepting a thisArg. You, too, can write your own function taking a callback function and thisArg:

function doWork(callbackfn, thisArg) {
    //...
    if (callbackfn != null) callbackfn.call(thisArg);
}

EDIT:

I forgot a special case. When constructing a new object via the new operator, the JavaScript interpreter creates a new, empty object, sets some internal properties, and then calls the constructor function on the new object. Thus, when a function is called in a constructor context, the value of this is the new object that the interpreter created:

function MyType() {
    this.someData = "a string";
}

var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);

QUIZ: Just for fun, test your understanding with the following examples.

To reveal the answers, mouse over the light yellow boxes.

  1. What is the value of this at line A? Why?

    <script type="text/javascript">
    if (true) {
        // Line A
    }
    </script>
    

    window

    Line A is evaluated in the initial global execution context.

  2. What is the value of this at line B when obj.staticFunction() is executed? Why?

    <script type="text/javascript">
    var obj = {
        someData: "a string"
    };
    
    function myFun() {
        // Line B
    }
    
    obj.staticFunction = myFun;
    
    obj.staticFunction();
    </script>
    

    obj

    When calling a function on an object, ThisBinding is set to the object.

  3. What is the value of this at line C? Why?

    <script type="text/javascript">
    var obj = {
        myMethod : function () {
            // Line C
        }
    };
    var myFun = obj.myMethod;
    myFun();
    </script>
    

    window

    In this example, the JavaScript interpreter enters function code, but because myFun/obj.myMethod is not called on an object, ThisBinding is set to window.

    This is different from Python, in which accessing a method (obj.myMethod) creates a bound method object.

  4. What is the value of this at line D? Why?

    <script type="text/javascript">
    function myFun() {
        // Line D
    }
    var obj = {
        myMethod : function () {
            eval("myFun()");
        }
    };
    obj.myMethod();
    </script>
    

    window

    This one was tricky. When evaluating the eval code, this is obj. However, in the eval code, myFun is not called on an object, so ThisBinding is set to window for the call.

  5. What is the value of this at line E?

    <script type="text/javascript">
    function myFun() {
        // Line E
    }
    var obj = {
        someData: "a string"
    };
    myFun.call(obj);
    </script>
    

    obj

    The line myFun.call(obj); is invoking the special built-in function Function.prototype.call(), which accepts thisArg as the first argument.