← JavaScript

Functions

What is `this` in JavaScript and how is its value determined?

Show answer — try answering out loud first

this is a reference to the execution context. Its value doesn't depend on where the function is defined, but on how it's called. Arrow functions are the exception: they inherit this from the scope where they are created.

The value of this changes depending on how you call the function:

  1. Method of an object (obj.metodo()): this is the object (obj).
  2. Standalone function (funcion()): this is undefined in strict mode, or the global object otherwise.
  3. With new: this is the new object being created.
  4. With call, apply, or bind: this is whatever you specify.
  5. Arrow function: it has no this of its own; it uses the one from the scope where it was defined.

The key: pay attention to how the function is invoked, not where it's written.

// 1. Method of an object
const usuario = {
  nombre: "Mike",
  saludar() {
    console.log(this.nombre);
  },
};
usuario.saludar(); // "Mike" (this is usuario)

// 2. The same function, but "standalone", loses this
const independiente = usuario.saludar;
// independiente(); // undefined (this is no longer usuario)

// 3. bind fixes this
const enlazada = usuario.saludar.bind(usuario);
enlazada(); // "Mike"

// 4. An arrow inherits this from the scope
const equipo = {
  nombre: "DevByMike",
  miembros: ["Ana", "Luis"],
  listar() {
    this.miembros.forEach((m) => {
      // the arrow uses the this from listar, which is equipo
      console.log(`${m} pertenece a ${this.nombre}`);
    });
  },
};
equipo.listar();
// "Ana pertenece a DevByMike"
// "Luis pertenece a DevByMike"

Assuming that this depends on where the function was written. In reality it depends on how it's called. That's why, when you store a method in a variable and call it standalone (const f = obj.metodo; f();), this stops being the object.

"this is a reference to the execution context, and the key point is that its value depends on how the function is called, not on where it's defined. If I call a method with obj.metodo(), this is obj. If I call the function standalone, this is undefined in strict mode. With new it's the new object, and with call, apply, or bind I decide what it is. Arrow functions are the exception: they inherit this from the scope where I wrote them."

Quick challenge

What does this print?

const contador = {
  total: 0,
  incrementar() {
    this.total++;
  },
};
const inc = contador.incrementar;
inc();
console.log(contador.total);
See answer

It prints 0 (and in strict mode it will probably throw an error). By storing the method in inc and calling it standalone, this is no longer contador, so it doesn't increment contador.total.