Member preview

The “this” keyword in Javascript.

There seems to be a lot of confusion in the industry about how the this keyword works in Javascript. The purpose of this article is to share my exploration and some tests designed to reach a better understanding of this keyword mechanism.

Global Context

In Javascript, this is a context-sensitive keyword. It means its reference can change depending on how you execute a given function. By default, the this keyboard is bound to the object that’s executing the function.

In a browser environment the window object and the this keyword are equivalent.

The image above is a browser environment (The global Object is Window).

Where this gets really confusing is when executing a function and then trying to refer to the same function by utilizing the this keyword.

Why this return undefined?

For those who come from a traditional object-oriented programing language, they would probably expect that this.bar refers to the variable bar within the function scope but as mentioned before, the this keyword gets bound to the object that’s executing the function (in this case the Window Object). since the bar property doesn’t exist within the Window Object. this will return undefined.

In Javascript functions declared in the global scope will be bound as a child of the global object.

to prove it can execute the following exercise.

Since the abcd() function has been declared in the global scope it becomes a child of the window object. Under that understanding we can say:

Executing the function as abcd() is equivalent to do it as window.abcd()

Methods

Once a function gets executed the this keyword will be bound to the parent object. That is exactly what we have done so far, nothing new yet… It’s just instead of the window Object, the this keyword will be bound to the parent object.

In order to execute this function we need to access to the bedroom Object. The site of execution will look as bedroom.getFurniture(). The this keyword will be bounded to bedroom(parent Object).


Constructor Function

It’s important to remember two things when dealing with constructor functions.

  • The naming convention to be used is Pascal-case
  • We have to use the keyword new to execute them.
This example will log a new object with two properties (furniture and owner)

By using the new keyword to execute the Bedroom function 3 things just happened in the background:

  • A brand new empty Object was created
  • The This keyword was bound to that Object
  • All the Bedroom’s properties were added to the object

Context manually assigned

Every function’s prototype object provides 2 methods to manually bind the this keyword. (bind | apply). By utilizing these methods we can choose which object should serve as a context for our function execution.

What we did in the example above we can list it in 3 simple steps:

  • Line 4— We created an object with one property furniture
  • Line 9— We declare a function in the global scope to return the furniture property of its context object.
  • Line 18, 19 — We are executing the function and manually binding the the this keyword to the furniture object.

What is the difference between .bind / .call / .apply?

The difference between these two methods is quite simple:

.call(this, arguments): This method takes two arguments:
1- the object to be assigned to the this keyword.
2- The arguments to be passed as we execute the function
.apply(this, arguments): This method takes two arguments:
1- the object to be assigned to the this keyword.
2- The arguments “as an array” to be passed as we execute the function

.Bind

This method will return a brand new function binding the this keyword permanently regardless of how the function’s call-site looks like.

.bind(this, arguments): This method takes two arguments:
1- the object to be assigned to the this keyword.
2- The arguments to be passed as we execute the function

A little challenge…

Now that we understand the context keyword… What is the following code logging to the console?

The code above logs undefined(3 times)

Why this behavior? why undefined? why 3 times?

The reason is that myCallback function is not a method of the todo object. In fact… it has nothing to do with the todo object. Its execution context is the Global Object.

Analysis

Based on the call-site todo.getList() we know the this keyword will be bound to the todo Object.

Let’s explain all the things that happen in line 4:

  • This is pointing to the list object inside of todo. This means we can access the list using this.list.
  • The list’s property is an Array data-type that contains (3) items, so it will inherit the method .map from its prototype.
  • .map is a high order function that takes another function callback as its argument and it will run this function against every element in the array(in this case 3).
  • Functions and every object in Javascript are passed as reference. Every function has its own this keyword and in the case of a callback it will hold a closure with the global Object.

Remember… in Javascript, we have functions as first-class citizens. This means that we can pass functions as arguments to other functions to be executed later on. Functions that take other functions as arguments are known as High-order functions and the functions passed as arguments are what known as callback functions.

Callback function can have identifier names or can be anonymous. It is highly recommended that we give them names to make our call stack more readable when debugging your web applications.