El temido "this" en JavaScript, de una vez por todas

A laptop displaying code in a modern indoor setting with an orange plush toy nearby.
Foto de Daniil Komov en Pexels

Si llevas tiempo programando en JavaScript, seguramente te ha surgido la duda (o el terror) de qué apunta this en cada contexto. No estás solo: el comportamiento de this es una de las preguntas más frecuentes entre principiantes y hasta entre desarrolladores con experiencia.

¿Qué es this?

En esencia, this es una referencia al objeto que está ejecutando la función actual. A diferencia de otros lenguajes, JavaScript no enlaza this en el momento de la definición, sino en el momento de la llamada.

Reglas básicas según el modo de llamada

  • Llamada directa: función() → this es undefined en strict mode y el objeto global (window en el navegador) en modo no estricto.
  • Método de objeto: objeto.metodo() → this es objeto.
  • Constructor con new: new Clase() → this es la nueva instancia creada.
  • Funciones flecha: heredan this del entorno léxico donde se definieron, sin crear su propio this.

Ejemplo práctico: método vs función

Veamos dos fragmentos que a simple vista parecen iguales, pero cuyo this varía.

const persona = {
  nombre: 'Ana',
  saludar: function() {
    console.log('Hola, soy ' + this.nombre);
  }
};

persona.saludar(); // Hola, soy Ana

const saludar = persona.saludar;
saludar(); // En modo estricto: TypeError (this is undefined)

En la primera llamada, saludar se invoca como método de persona, por lo que this apunta al propio objeto. En la segunda, la función se extrae y se ejecuta sin contexto, por lo que this pierde referencia.

El truco de bind, call y apply

Si necesitas forzar el valor de this, JavaScript te ofrece tres métodos:

  • func.bind(obj) devuelve una nueva función con this permanentemente enlazado a obj.
  • func.call(obj, arg1, arg2) invoca la función inmediatamente con this igual a obj y los argumentos especificados.
  • func.apply(obj, [arg1, arg2]) funciona como call pero recibe los argumentos como un array.

Ejemplo:

function presentar(saludo) {
  console.log(saludo + ', soy ' + this.nombre);
}

const usuario = { nombre: 'Luis' };

const presentarUsuario = presentar.bind(usuario);
presentarUsuario('¡Hey'); // ¡Hey, soy Luis

presentar.call(usuario, 'Hola'); // Hola, soy Luis
presentar.apply(usuario, ['Buenas']); // Buenas, soy Luis

Funciones flecha: el aliado de los callbacks

Los callbacks dentro de métodos de clase son una fuente habitual de confusión. Las funciones flecha resuelven el problema porque no crean su propio this, sino que lo capturan del entorno donde se definieron.

class Contador {
  constructor() {
    this.cuenta = 0;
  }
  iniciar() {
    setInterval(() => {
      this.cuenta++;
      console.log(this.cuenta);
    }, 1000);
  }
}

const c = new Contador();
c.iniciar(); // incrementa cada segundo sin perder referencia a "this"

Si hubiéramos usado una función tradicional dentro de setInterval, this se referiría al objeto global y el contador fallaría.

Consejos para evitar sorpresas

  • Usa funciones flecha para callbacks que necesiten acceder a propiedades de la clase u objeto contenedor.
  • Cuando declares métodos dentro de objetos literales, mantén la sintaxis metodo() { … } (ES6) para que el this sea claro.
  • En entornos estrictos ('use strict') this nunca será el objeto global por accidente.
  • Revisa siempre el contexto antes de pasar una función como argumento; si es necesario, enlázala con bind.

Resumen rápido

El comportamiento de this depende del cómo se llama a la función:

  • Método de objeto → this = objeto
  • Constructor con new → this = instancia
  • Función normal → this = undefined (strict) o window (non‑strict)
  • Función flecha → this heredado del entorno léxico

Con estas reglas claras y los trucos de bind/call/apply, podrás domar al temido this y escribir código más predecible y mantenible.