Yeison Daza
4 min read

Understanding this in JavaScript

this is a JavaScript keyword that behaves very differently from other programming languages, which is why some people consider it one of the biggest design mistakes in the language.

The key to understanding how this works is knowing where it’s being invoked, so you can figure out which object gets assigned to it.

Where is this being invoked?

Implicit Binding

Case 1

In this first case, this is being invoked inside a method.

let yo = {
  nombre: 'yeison',
  edad: 22,
  hablar: function () {
    console.log(this.nombre);
  }
};

yo.hablar(); // yeison

this refers to the object that contains the method where it’s invoked.

Case 2

In this case, we have a function that receives an object as a parameter and adds a method called hablar to it. Then, the function is called on two objects.

let decirNombre = function(obj) {
  obj.hablar = function() {
  console.log(this.nombre);
  };
};

const Mateo = {
  nombre: 'Mateo',
  edad: 22
};

const juan = {
  nombre: 'Juan',
  edad: 25
};

decirNombre(juan);
decirNombre(Mateo);

juan.hablar(); // Juan
Mateo.hablar(); // Mateo

This in this case refers to the object that the method was added to.

Case 3

In this case we have a function that returns an object containing a hablar method that invokes this.

let Persona = function (nombre, edad, madre) {
  return {
    nombre: nombre,
    edad: edad,
    hablar: function() {
      console.log(this.nombre);
    },
    madre: {
      nombre: madre,
      hablar: function() {
        console.log(this.nombre);
      }
    }
  };
};

const ana = Persona('Ana', 30, 'Clara');

ana.hablar(); // Ana
ana.madre.hablar(); // Clara

This in this case refers to the object that contains the method where it’s invoked.

As we saw in all 3 cases, when this is invoked inside a method, it implicitly refers to the object that contains the method, regardless of whether the method was added after the object was created, or whether it’s a function that returns an object.

Here you can find the code from these examples, so you can play around and see how it works.

Explicit Binding

In the case of implicit binding, this refers to the object that contains the method where this is invoked. But what if we have a function and we want to explicitly assign what this should refer to? Since ES5, we have the call(), apply(), and bind() methods for that.

Let’s say we have a function that takes some parameters and logs to the console the nombre property that this references, along with the parameters it receives.

const hablar = function(l1, l2, l3) {
  console.log(`Hola mi nombre es ${this.nombre}
                y se programar en ${l1}, ${l2}, ${l3}.`);
};

const yeison = {
  nombre: 'Yeison',
  edad: 22
};

const lenguajes = ['JavaScript', 'Python', 'C']

Now, we need to reference the yeison variable so that it becomes this.

call()

hablar.call(yeison, lenguajes[0],lenguajes[1],lenguajes[2]);

The call method lets us define what this will refer to in its first parameter. The remaining parameters are the arguments that the function receives.

apply()

hablar.apply(yeison, lenguajes);

The apply method works just like call, letting you reference this in the first parameter, but it allows you to pass an array as the function’s arguments.

bind()

This method works differently from the previous ones. It returns a new function where this refers to the object you pass as its parameter.

const hablaYeison = hablar.bind(yeison, lenguajes[0],lenguajes[1],lenguajes[2]);

hablaYeison();

These three methods allow us to create an explicit reference and be clear about the value of this during execution.

Here you can find the code from these examples, so you can play around and see how it works.

Binding with new

Another case is when we invoke this inside a constructor, like in the following example:

let Animal = function(color, nombre, tipo) {
  this.color = color;
  this.nombre = nombre;
  this.tipo = tipo;
}

const bipa = new Animal('gris', 'Bipa', 'Felino');

In this case, this refers to the object being instantiated.

Here you can find the code from this example, so you can play around and see how it works.

Binding to window

One of the biggest design mistakes with the this keyword is that when there’s no reference to an object that represents this, it defaults to the window object.

In ES2015 or if you use use strict, it refers to undefined instead.

const decirEdad = function() {
  console.log(this.edad);
};

const yo = {
  edad: 22
};

Let’s take this example: we have a function that displays the edad property of whatever object this references. But what happens if we do something like this:

decirEdad();
window.edad = 24;
decirEdad(); //24

We’re calling the function without assigning an object to it.

In this case, this refers to the window object. If we assign an edad property to the window object and run the function again, we can see it gets displayed.

This is a big security issue. To make things a bit safer, we can use the ‘use strict’ statement like this:

const decirEdad = function() {
  'use strict';
  console.log(this.edad);
};

In this case, if we accidentally call the function without assigning an object, it will throw an error, since this refers to undefined and undefined doesn’t have an edad property.

Here you can find the code from this example, so you can play around and see how it works.