'this' in JavaScript function.

Example oriented explanation of 'this' in JavaScript function, ES5 and ES6.

Updated on 12/09/18
10 minute read

Disclosure

Webquestions.co is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for us to earn fees by linking to Amazon.com and affiliated sites. As an Amazon Associate I earn from qualifying purchases.

this keyword. 

A notorious topic for beginners and experienced programmers alike. 

Though ES6 brought some changes to this topic, it is still a must to master in order to become a great programmer. 

In this article I will explain the this in JavaScript function with examples, and what ES6 brought to change the behavior.

 

In this article I will take a unique approach.

Since understanding this is best through examples, I will explain a principle in one line, and then we are going to practice it via examples. 

 

Related:

 

this prior to ES6 (ES5 and below)

 


"this in JavaScript function is set by the call or defaults to another value if not set."


 

Take a second to think about that.

this in JavaScript function is set by the call. Sometimes, it is not being set by any call, and it defaults to a different value. That is a big part of the source of confusion with the topic.

In JavaScript like JavaScript, there are some irregularities, I will address them later. 

For the moment, let's continue with the definition above in mind - this is set by the call, if not set, it will default to other value. 

 

example 1: simple function call from within an object.

var object = {

    a: "some text",
    b: function() {
        console.log(this);
    }

}

object.b();

//{a: "some text", b: ƒ}

You can clearly see that it was an object that called the function b. Therefor, this will refer to object

The object sets the value of this to point to it. 

 

example 2: object inside an object.

var obj = {
  a: "text",
  b: {
    c: function() {
      console.log(this)
    },
	d: "some value"
  }
}

obj.b.c();

//Result: {c: ƒ, d: "some value"}

In this example, we call the function c()

The object that is calling c() is object b. not objthis will refer to the calling object, in this case, b.

 

example 3: calling a function from the window object.

function callMe() {
    console.log(this);
}

callMe();

//{window}

In this example, it seems that callMe() isnt called by any object. It is a stand alone function.

Declaring a function like that, when the function is declared outside of any object, actually declares the function as a window object property. Try it in your browser / JS playground (JSBin, JSfiddle).

It is as if we called window.callMe(). That is why the this reference points to the window object that calls the function. 

 

example 4: calling a function from within a function. 

function outer() {

    function inner() {

        console.log(this);

    }

    return inner();

}

outer();

//{window}

In this example, we got the same result. The window object.

The inner() function is not called by any other object. Therefor, it will default to the window object.

 

example 5: calling a function from within a function. First function is declared inside an object.

What do you think will happen here? Take a moment to think about that.

var obj = {

    callMethod: function () {

        function inner() {
  
            console.log(this);

        }

        return inner();

    }

}
obj.callMethod();

 

JavaScript caveat: In this case this will refer to the window object, even though obj invoked the method.

It is something you need to remember, that is just how JavaScript works. 

When inner() function is declared, this inside inner() loses its reference and defaults to the window object. 

For now, that is the take away point out of this example: No matter how deep your are in objects, when a function is invoked and the this was not set by the call, it will default to the window object. In this case, inner() is invoked without setting the this to any value by the call. 

 

example 6: declaring an object method using a function that was lexically declared outside of the object.

function outSide() {
  console.log(this);
}

var obj = {
  
  someProp: "Text",
  callMe: outSide
  
}

obj.callMe();

Here we assigned the function outSide() as a value for the property callMe

When we call it, the result will be {someProp: "Text", callMe: ƒ} since obj is calling the method and it doesn't matter that the invoked function was lexically declared outside, under the window object. 

The call set the value of this to point to obj since the latter called the function.

 

example 7: That's a tricky one. Similar to example 4 but this time what returns is an object invoking a function. 

What do you think will happen?

function outer() {

    function inner() {
      
        var innerObject = {
          
          method: function() {
            
            console.log(this);
            
          }
          
        }

        return innerObject.method();

    }

    return inner();

}

outer();

outer() is invoked. It returns the invoked inner()

The invoked inner() has an object in its scope. The object contains a method. The invoked inner() returns the object calling its method.

The result{method: ƒ} will be logged to the console.

Why is that if we saw that a function within a function will default to the window object (JavaScript caveat)?

because here, the most inner function returns an object that invokes a function. And since a this in a function will refer to the calling object, {method: ƒ} is returned. Another way to look at it is the innerObject sets the this to refer to the caller, itself.

 


"strict mode changes the way this behaves"


 

strict mode was introduced in ES5. 

Among other changes the feature adds, there is a change in the behavior of this reference. 

 

example 8: invoking a function from within a function. Similar to example 4, but now, in strict mode

"use strict";

function outer() {

    function inner() {

        console.log(this);

    }

    return inner();

}

outer();

//undefined

 

Now we can see that unlike example 4, this will not default to window object.

If not specified by the call, this will default to undefined.

That is the major difference for that matter.  

 

To conclude ES5 and prior:

this is set by the call.

Every function has its own this. Either set by the call or by default behavior.

this will refer to the invoking object, if none is present to set this, it will default to the window object. 

strict mode changes the default value of this when not set by the call. 

As I mentioned, there are some caveats and solutions for them.
I will address them all in later section.   

 

Here is a table to summarize the possible this values in the above cases:

 

this will refer to: / mode No Strict mode In Strict mode
Set by call The calling object.

The calling object.

Not set by  the call window object undefined

 

this in ES6 and beyond

ES6 introduced arrow functions. 

Arrow functions are here to solve some of the mess above and retain the this of the surrounding context. 

 


"arrow functions do not have their own this, they inherit it from the outer context."


 

example 9: declaring an arrow function on the window object (global context).

const callMe = () => {
	console.log(this);
}

callMe();

//{window}

This is pretty straight forward. 

Now we know that the arrow function will inherit its lexical contexts this.  

The context in which callMe() was declared is the global context (window object) so this will refer to it. 

 

example 10: A tricky and long example - declaring a function within an object (object method).

Similar on example 5, what will be logged to the console?

const obj = {

    callMethod: () => {

        const inner = () => {
  
            console.log(this);

        }

        return inner();

    }

}

obj.callMethod();

Will the this point to obj? I mean we said that arrow function will inherit the reference to this so should it point to the object obj?

NO. that is the tricky part.

Since callMethod() is an arrow function, it never receives a meaningful this. We said that arrow function do not have their own this.

Since there was no this created for any function above it, it inherited the this that referenced to the global object. 

 

So what can we do?

There is a rule of thumb: when declaring object method, always create "regular" function expression or function statements.

Here is an example (we are still in example 10):

const obj = {

    callMethod: function () {  //this is not an arrow function. It will create a 'this' reference to 'obj'

        const inner = () => {
  
            console.log(this);

        }

        return inner();

    }

}

obj.callMethod();

 

Notice the subtle change. callMethod() was declared as a "regular" function.

Now the result of obj.callMethod? {callMethod: ƒ} .

 

example 11: Similar to example 7. What will this refer to?

const outer = () => {

    function inner() {
      
        let innerObject = {
          
          method: () => {
            
            console.log(this);
            
          }
          
        }

        return innerObject.method();

    }

    return inner();

}

outer();

Notice how functions are declared in the example. 

Look for arrow functions (that inherits their this) and for non-arrow functions that either get thier this by the caller or default to a value. 

The result: window object.

Why? 

Notice innerObject method declaration. It is an arrow function. Since no this was set above it, it will inherit the window reference.

How can you make it show innerObject as this

Declare the object method using a non-arrow function.

 

example 12: same as example 11, but under strict mode

What will this refer to?

"use strict"; //the only change

const outer = () => {

    //..... 
    //same code
    //....

}

outer();

undefined.

We said that under strict mode, if not set by the call, this will not default to the window object but to undefined.

 

To conclude ES6 and beyond

Arrow functions inherits their this reference from the outer context.

In many situations, both ES5 and ES6 behavior regarding this is similar. 

When you want to create a meaningful this, use regular functions, not arrow functions (mainly when creating objects methods.)

 

What is next

The above explanation of this in jacascript function may provide a solid basis to understanding the topic. 

I recommend further reading of the following topics: 

  1. bind(), call() and apply().
  2. The use of this in a constructor.
  3. this in events and events callbacks.