TechLead

La Palabra Clave 'this'

Cómo funciona 'this' en diferentes contextos: global, objeto, funciones flecha, bind/call/apply

Comprender 'this' en JavaScript

La palabra clave this es uno de los aspectos más confusos de JavaScript. A diferencia de otros lenguajes donde this siempre se refiere a la instancia actual, en JavaScript this depende de cómo se llama una función, no de dónde se define.

Las 4 Reglas de 'this'

  1. Vinculación Predeterminada — Objeto global (o undefined en modo estricto)
  2. Vinculación Implícita — El objeto que llama al método
  3. Vinculación Explícita — Establecido manualmente via call, apply o bind
  4. Vinculación new — El objeto recién creado

1. Vinculación Predeterminada

Cuando una función se llama independientemente (no como método), this se refiere al objeto global (o undefined en modo estricto):

function mostrarThis() {
  console.log(this);
}

mostrarThis(); // Window (navegador) o global (Node)

// En modo estricto
"use strict";
function mostrarThisEstricto() {
  console.log(this);
}

mostrarThisEstricto(); // undefined

2. Vinculación Implícita

Cuando una función se llama como método de un objeto, this se refiere a ese objeto:

const usuario = {
  nombre: "Alice",
  saludar() {
    console.log(`Hola, soy ${this.nombre}`);
  }
};

usuario.saludar(); // "Hola, soy Alice" — this = usuario

// ⚠️ Perdiendo vinculación implícita
const fnSaludar = usuario.saludar;
fnSaludar(); // "Hola, soy undefined" — this = global/undefined

// Común en callbacks
setTimeout(usuario.saludar, 1000); // "Hola, soy undefined"

3. Vinculación Explícita: call, apply, bind

Forzar que this sea un valor específico:

function presentar(saludo, puntuacion) {
  console.log(`${saludo}, soy ${this.nombre}${puntuacion}`);
}

const persona = { nombre: "Bob" };

// call — argumentos pasados individualmente
presentar.call(persona, "Hola", "!");  // "Hola, soy Bob!"

// apply — argumentos pasados como array
presentar.apply(persona, ["Hola", "."]);  // "Hola, soy Bob."

// bind — retorna una nueva función con 'this' fijo
const presentacionFija = presentar.bind(persona);
presentacionFija("Hey", "?");  // "Hey, soy Bob?"

// Aplicación parcial con bind
const decirHolaABob = presentar.bind(persona, "Hola");
decirHolaABob("!");  // "Hola, soy Bob!"

4. Vinculación new

Al usar new con un constructor, this se refiere al objeto recién creado:

function Persona(nombre) {
  // 'this' es el nuevo objeto que se está creando
  this.nombre = nombre;
  this.saludar = function() {
    console.log(`Hola, soy ${this.nombre}`);
  };
}

const alice = new Persona("Alice");
alice.saludar(); // "Hola, soy Alice"

// Lo que hace 'new':
// 1. Crea un nuevo objeto vacío
// 2. Lo enlaza a Persona.prototype
// 3. Vincula 'this' al nuevo objeto
// 4. Retorna el objeto (si no hay return explícito)

Funciones Flecha: 'this' Léxico

Las funciones flecha no tienen su propio this. Heredan this de su ámbito externo:

const obj = {
  nombre: "Objeto",
  
  // Función regular — tiene su propio 'this'
  metodoRegular() {
    console.log(this.nombre); // "Objeto"
    
    // Problema: función anidada pierde 'this'
    setTimeout(function() {
      console.log(this.nombre); // undefined
    }, 100);
  },
  
  // Función flecha — hereda 'this'
  metodoFlecha() {
    console.log(this.nombre); // "Objeto"
    
    // Solución: flecha hereda 'this' de metodoFlecha
    setTimeout(() => {
      console.log(this.nombre); // "Objeto" ✓
    }, 100);
  }
};

obj.metodoRegular();
obj.metodoFlecha();

⚠️ Nota: Las funciones flecha no pueden usarse como constructores y no pueden vincularse con call/apply/bind.

'this' en Clases

class Contador {
  constructor() {
    this.cuenta = 0;
    
    // Método 1: Vincular en constructor
    this.incrementarVinculado = this.incrementar.bind(this);
  }
  
  incrementar() {
    this.cuenta++;
    console.log(this.cuenta);
  }
  
  // Método 2: Propiedad de función flecha
  incrementarFlecha = () => {
    this.cuenta++;
    console.log(this.cuenta);
  };
}

const contador = new Contador();

// Método regular pierde 'this' cuando se extrae
const inc = contador.incrementar;
inc(); // Error: No se puede leer la propiedad 'cuenta' de undefined

// Método vinculado funciona
const boundInc = contador.incrementarVinculado;
boundInc(); // 1

// Propiedad flecha funciona
const arrowInc = contador.incrementarFlecha;
arrowInc(); // 2

Prioridad de Vinculación

Cuando se aplican múltiples reglas, orden de prioridad (de mayor a menor):

Prioridad Tipo de Vinculación Ejemplo
1 (mayor) Vinculación new new Fn()
2 Vinculación explícita fn.call(obj)
3 Vinculación implícita obj.fn()
4 (menor) Vinculación predeterminada fn()

💡 Puntos Clave

  • this está determinado por cómo se llama una función, no dónde se define
  • • Usa bind, call o apply para establecer this explícitamente
  • • Las funciones flecha heredan this de su ámbito externo
  • • En clases, usa propiedades flecha o vincula métodos para preservar this
  • • En caso de duda, console.log(this) para ver a qué se refiere

Ejercicios rápidos de práctica

  • • Toma un componente React, extrae un handler y predice cómo cambia this cuando se pasa sin vincular.
  • • Crea un pequeño snippet que registre this bajo cada regla (predeterminada, implícita, explícita, new) y anota los resultados.
  • • Depura una prueba fallida reemplazando una función por una función flecha; nota por qué this léxico lo arregla o rompe.
  • • En Node, compara this dentro de módulos ES vs CommonJS para internalizar las diferencias de vinculación a nivel de módulo.