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

HTML code displayed on a screen, demonstrating web structure and syntax.
Foto de anshul kumar en Pexels

El operador this es una de las fuentes más comunes de dudas en JavaScript, sobre todo cuando se combinan funciones tradicionales, arrow functions y el modo estricto. En este artículo vamos a despejar los conceptos clave y a ver, paso a paso, cómo se determina el valor de this en los distintos contextos.

¿Qué representa this?

En JavaScript this es una referencia al objeto que está ejecutando la función actual. No es una variable que se declara, sino un binding que el motor asigna en tiempo de ejecución según cómo se invoque la función.

Reglas de enlace en funciones tradicionales

Para funciones declaradas con la sintaxis clásica (function foo() {}) el valor de this se decide siguiendo estas reglas:

  • Invocación directa: foo()this es undefined en modo estricto o el objeto global (window en el navegador) en modo no estricto.
  • Método de objeto: obj.metodo()this es obj.
  • Constructor: new Foo()this es la nueva instancia creada.
  • call / apply / bind: permiten fijar explícitamente el valor de this.

Arrow functions y el this léxico

Las arrow functions (() => {}) no crean su propio this. En su lugar capturan el valor de this del contexto donde se definieron, de forma similar a lo que ocurre con las closures.

Ejemplo práctico

Veamos un caso típico donde la confusión surge al usar callbacks dentro de un método de objeto.

const contador = {
  total: 0,
  incrementar() {
    // this aquí es contador
    setTimeout(function() {
      // función tradicional: this apunta al objeto global
      this.total++; // ❌ No afecta a contador.total
    }, 100);
  }
};

contador.incrementar();

En el ejemplo anterior, this.total no se actualiza porque la función pasada a setTimeout pierde el contexto original. Tenemos tres soluciones habituales:

  • Usar bind para fijar el this:
setTimeout(function() {
  this.total++;
}.bind(this), 100);
  • Almacenar la referencia en una variable (const self = this;) y usarla dentro del callback.
setTimeout(function() {
  self.total++;
}, 100);
  • Utilizar una arrow function, que hereda el this léxico:
setTimeout(() => {
  this.total++;
}, 100);

La tercera opción es la más concisa y, en la mayoría de los casos, la que recomiendo.

El papel de strict mode

Activar el modo estricto ('use strict';) evita que this se convierta implícitamente en el objeto global. Así, una llamada directa a una función sin contexto producirá undefined, lo que ayuda a detectar errores temprano.

Resumen rápido

  • En funciones tradicionales, this depende de cómo se invoque la función.
  • En arrow functions, this se hereda del entorno donde se declararon.
  • Usa bind, variables auxiliares o arrow functions para mantener el contexto dentro de callbacks.
  • El modo estricto hace que los errores de contexto sean más visibles.

Dominar el comportamiento de this te permitirá escribir código más predecible y evitar bugs difíciles de depurar. ¡Ánimo y a seguir codificando!