Javascript – What is ‘this’?

Javascript – What is ‘this’?

There two kinds of people who write Javascript in the world: the ones that don’t know understand this and good JS developers.

The edge cases of using this is one of the main struggle of beginners and one of the most favorite topic in job interview. In this article we will analyze the concept behind  it so you won’t worry about it again.

 


What is this?

The important thing to acknowledge from the start is that the keyword this holds a reference to an object. There are only two situations when you can encounter it: in the global scope and inside a function.

The object in most cases refers to the context in which a a code is executed.  In the global scope, the global object window has this role. Inside a function, this reference the so-called receiver object.

 


This in the global scope

When this is used in the global scope, this refers to (and has the value of) the window object. As we know from the article about scope, in the global scope, all global variables and functions are defined on the window object. Moreover, every variable that is declared without var is also automatically bound to the global object window.

The cases where you would want to use this in the global context are pretty rare, this is why strict mode introduced in ECMAScript 5 changes the value of this in the global scope to undefined. This way, it is more likely to acknowledge a situations where this is misused (since trying to access a property of undefined will throw an error).

 


This inside a function

In the article about functions,  we saw that the function in Javascript is just an object with a set of particular properties – the list of arguments, the prototype and this -.

As we saw before, inside a function, this reference the receiver object.  The receiver is the object that invokes the function. So this is not assigned a value until an object invokes the function.

I cannot stress this enough! If you want to know what this represent inside a function, you will have to look where that function is called.

The value of this is defined only when the function is called and it’s exclusively on the object that invokes the this Function.

One particularity about Javascript is that it doesn’t have a clear distinction between function calls, methods and constructors. All three roles are served by the function. And every function in Javascript can be used as one of the three.

If used in the right way, this versatility is a very powerful feature of the language and the receiver object has an important part in it.

 


1. Simple function calls

function sayHi() {
   return "Hi " + this.first_name; 
};

Looking just at the body of the function there is no way to predict what is going to return, since we don’t know yet what the value of this is.

sayHi(); // Hi, undefined

If we are going to call the function in the global scope, it will return “Hi, undefined” (or even an error if we run in strict mode). There is no much usage for it.

 


2. Methods

Methods in Javascript are nothing more than object properties that happen to be functions.

var obj = {
    firstname: "John",
    sayHi: function() {
    return "Hi, " + this.firstname; 
 }
}

obj.sayHi(); // 'Hi, John'

Notice how sayHi refers to this to access the properties of obj. You might be tempted to assume that this gets bound to obj because the sayHi method was defined on obj. But that is not the case. obj is the receiver object because it was used to invoke the function.

If we simply copy the function to a global variable and call it, this will represent the global object again. We can also use the same reference as an attribute for a different object.

obj.sayHi(); // 'Hi, John' 

f = obj.sayHi;

var obj2 = { 
   firstname: "Nick",
   sayHi: obj.sayHi
}
// we call the same function but from the global context
f(); // 'Hi, undefined'

// we call the same function with obj2 as receiver object
obj2.sayHi(); // 'Hi, Nick'

Once we understood that, we can easily debunked another common misunderstanding – callbacks -.

var myButton = {
    name: "btn",
    onClickEvent: function() {
        alert("You clicked " + this.name);
     }
}

$("button").click(myButton.onClickEvent); // 'You clicked undefined'

Again, many people assume that since onClickEvent is a myButton attribute, this will point to myButton. In reality, the $("button") – which is a jQuery object – is the one that invokes the function so it will be the receiver object.

 


3. Constructors

Functions can be also used as constructors in Javascript alongside with the new keyword. When calling obj = new Car() the following things are occur behind the scenes:

  • a generic object is created
  • the __proto__ of the object is set to Car.prototype
  • the Car function is called, with this representing the newly created object (so name will be added on object)

The prototype inheritance is outside the scope of this article but you can find more details here.

The constructor function will be able to reference the new object via this and add the the attributes needed at initailization

The important thing to take from here is: when a function is used a constructor, this reference a generic object (the new ‘instance’).

 


Watch out at nested functions

A common confusion occurs when dealing with nested functions (closures). As you many know, the nested function has access to the variables from the main function (the outer scope).

However, this is accessible only to the function itself, not the inner functions. 

var obj = {
    first_name: "John",
    sayHi: function() {
       var string = "Hi, ";
       function printer(message) {
          console.log(this.first_name); 
       }
       printer(string);
    }
};

obj.sayHi();

In this example, the value printed is “Hi, undefined”. The function printer is invoked through a simple function call, so the value of this is the global context.

The value of thisis related to the function call only and is not transmitted to the inner functions.

 


Use bind() to explicitly call a function with a different receiver

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. It belongs to Function.Prototype, so any function has access to it

Let’s see it in action:

var myButton = {
    name: "btn",
    onClickEvent: function() {
        alert("You clicked " + this.name);
     }
}

$("button").click(myButton.onClickEvent.bind(myButton)); 
//$("button").click(myButton.onClickEvent); // 'You clicked undefined'

This time, myButton.onClickEvent.bind(myButton) creates a new function in which this points to the myButton object.

Note: Similar to bind(), Javascript also provides apply() and call() methods. The difference is that they don’t create a new function like bind(), just simply call the function with a different this.

 


Things to remember

  • this holds a reference to an object and is encounter in 2 situations:
    • global scope – has the value of window (or undefined in strict mode)
    • inside a function – bound at invocation time – the value is defined only when the function is called and it’s exclusively on the object that invokes the this Function

Screen Shot 2017-09-21 at 10.41.13 AM

  • The value of this is related to the function call only and is not transmitted to the inner functions
  • this gives methods access to their objects
  • You can explicitly set the value of this for a function before using it (using bind(), apply() or call())

 

 


Final words

Javascript function are a versatile and very powerful weapon for scripting in browser.

I hope you will find this read helpful to understand it better!

Note: This is part of Javascript learning roadmap.

Thank you for your time!

Please subscribe for more weekly web wisdom!

One thought on “Javascript – What is ‘this’?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s