loading...

What is "this"? A quick look into "this" in JavaScript.

dtfocus profile image Danny Tseng Updated on ・5 min read

I come across the key word "this" a lot when working with JavaScript. It is a key word that is used quite often when working with JavaScript and you may have come across it yourself. It is also one of the interesting concepts in JavaScript that can often produce or yield unexpected results depending on the way it is used. Here is a quick post for identifying some of the scenarios and situations that "this" can be used and what the results may be produced from them.

Think of the keyword "this" as something that is created behind the scene when a function is created and linked to the object the function operates on. The value of "this" does not depend on the function itself but rather how the function is called. In short, the keyword "this" in JavaScript refers to the object it belongs to. Depending on the factors such as how the function is invoked and the default execution context the function is executed in, the results of the execution may vary.

I think one thing that may be confusing when discussing the use of "this" is the difference between scope and context. Scope is about the visibility of the variables while context is the object a function belongs to. It is important to differentiate the two since they are not the same and without the proper understanding of these two concepts that it may be difficult to grasp the use of the keyword "this" in JavaScript. Here is an article that explains the difference between the two.

The default context is the global context and in the case of JavaScript the window object. The code below is an example of declaring and calling function in a global context.

Normal Function Call

    function test() {
      console.log(this === window);
    }

    test(); //true

When you enter the above code in the browser console, the result should be true. Let's take a look at the same code that is called in a different way.


    function test() {
      console.log(this === window);
    }

    let x = {
      test: test
    }

    test(); //true

    x.test(); //false

Implicit Binding

The result of x.test is not true because the keyword "this" in this case is not the window but x which is the object the function or in this case method "test" belongs to. This is the used of implicit binding where you are creating a function inside an object. The second "test" in the line "test: test" is the same function that is declared at the top but it is stored inside x in order to make the connection between the object and function.

Let's look further into this example. Suppose now there is an attribute name in the object and the test function on the top has "this.name" instead of just "this" alone.


    function test() {
      console.log(this.name);
    }

    let x = {
      name: "John",
      test: test
    }

    test();

    x.test();

What would the results be? The answer for "test()" is nothing gets print out because the window object does not have a name property. As for the line "x.test()", "John" gets print out because it is one of the attributes of object x.

A little trick to determine which object the function belongs to is by looking at what is on the left side of the "." when making a call. A simple function call without "." usually means the function is linked to the default context which is the window object unless there is other bindings involved.

Built in methods like call(), apply(), and bind() are also other ways of binding function to an object. I won't get into the details of how call() and apply() work but they are basically called the "explicit binding" that you can use to bind functions to a specific object so you can call an object method with another object as argument. As for bind(), it is called "hard binding" when you bind an object to a function.

Hard Binding

    function test() {
      console.log(this.name);
    }

    let x = test.bind({name: "Doe"});

    x(); //"Doe"


When you use bind() to bind an object to a function, a new function will be created and the owner object of the new function will be the object that you bind the function with.

Here comes the little tricky part, what about the nested functions inside an object? What does the keyword "this" inside the nested functions refer to? Let's take a look at the example below.

    let x = {
      name: "John",
      test: function() {
        return function() {
          console.log(this.name)
        }
      }
    }

    x.test()();


What do you think the output of the line "x.test()()" is? This line is actually not going to print anything in the console. But wait, shouldn't the object be "x" therefore "this.name" should be "John"? This was my response when I encountered this particular example. This is the way I break this line down in a way to better understand why the answer is not "John."

For line,

    x.test()();

it can be broken down into the outer function and inner function.

    let outer = x.test //outer function
    let inner = x.test(); //inner function

The outer function belongs to the object x so if we have a console.log for printing out "this.name" in the outer function, the answer will be "John." However, in order to obtain the inner function you need to call "x.test()" because the outer function returns the inner function when invoked. Now that you have the inner function stored in a variable. The way to invoke the inner function is by making a simple function call like below.

    inner();

As such, since there is no object attached to this function call, the default context is used which is the window object. Since the window object doesn't have the "name" attribute, nothing is going to be printed out in the console but an empty string. In order to make the inner function prints out "John", bind() can be used on the inner function to achieve it.

    let x = {
      name: "John",
      test: function() {
        return function() {
          console.log(this.name)
        }
      }
    }

    let outer = x.test //outer function
    let inner = x.test(); //inner function
    inner = inner.bind(x)
    inner(); //"John"

JavaScript is a widely used language and it is imperative to have a good grasp of the concept of the keyword "this" in different contexts. There are other uses of the keyword "this" such as in the arrow function which the rules mentioned earlier don't really apply. This blog is meant to be a quick guide or refresher on the keyword "this" and some scenarios that we may encounter when working with JavaScript.

References
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
https://www.w3schools.com/js/js_this.asp
http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/
https://blog.kevinchisholm.com/javascript/difference-between-scope-and-context/

Discussion

pic
Editor guide