← JavaScript

Funciones

¿Qué es `this` en JavaScript y cómo se determina su valor?

Ver respuesta — intenta responderla en voz alta primero

this es una referencia al contexto de ejecución. Su valor no depende de dónde se define la función, sino de cómo se la llama. Las arrow functions son la excepción: heredan this del ámbito donde se crean.

El valor de this cambia según cómo llames a la función:

  1. Método de un objeto (obj.metodo()): this es el objeto (obj).
  2. Función independiente (funcion()): this es undefined en modo estricto, o el objeto global en otro caso.
  3. Con new: this es el nuevo objeto que se está creando.
  4. Con call, apply o bind: this es lo que tú especifiques.
  5. Arrow function: no tiene this propio; usa el del ámbito donde fue definida.

La clave: fíjate en cómo se invoca la función, no en dónde está escrita.

// 1. Método de un objeto
const usuario = {
  nombre: "Mike",
  saludar() {
    console.log(this.nombre);
  },
};
usuario.saludar(); // "Mike" (this es usuario)

// 2. La misma función, pero "independiente", pierde this
const independiente = usuario.saludar;
// independiente(); // undefined (this ya no es usuario)

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

// 4. Una arrow hereda this del ámbito
const equipo = {
  nombre: "DevByMike",
  miembros: ["Ana", "Luis"],
  listar() {
    this.miembros.forEach((m) => {
      // la arrow usa el this de listar, que es equipo
      console.log(`${m} pertenece a ${this.nombre}`);
    });
  },
};
equipo.listar();
// "Ana pertenece a DevByMike"
// "Luis pertenece a DevByMike"

Suponer que this depende de dónde se escribió la función. En realidad depende de cómo se la llama. Por eso, cuando guardas un método en una variable y lo llamas de forma independiente (const f = obj.metodo; f();), this deja de ser el objeto.

"this es una referencia al contexto de ejecución, y lo importante es que su valor depende de cómo se llama a la función, no de dónde se define. Si llamo a un método con obj.metodo(), this es obj. Si llamo a la función de forma independiente, this es undefined en modo estricto. Con new es el nuevo objeto, y con call, apply o bind decido qué es. Las arrow functions son la excepción: heredan this del ámbito donde las escribí."

Reto rápido

¿Qué imprime esto?

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

Imprime 0 (y en modo estricto probablemente lance un error). Al guardar el método en inc y llamarlo de forma independiente, this ya no es contador, así que no incrementa contador.total.