this en JavaScript no apunta a la función que lo contiene ni al objeto donde se define: apunta al contexto de invocación, es decir, a cómo se llama la función. Esta regla simple explica todos los comportamientos de this y todos los bugs que genera cuando no se tiene en cuenta.
this en el contexto global
En el ámbito global, fuera de cualquier función, this apunta al objeto global. En navegadores es window; en Node.js es global (o globalThis en versiones modernas):
// En el navegador console.log(this === window); // true // En modo estricto en el global, this sigue siendo el global 'use strict'; console.log(this === window); // true (en global) // En Node.js console.log(this === global); // false en módulos ES console.log(this === globalThis); // true en cualquier entorno
this en métodos de objeto
Cuando llamas a una función como método de un objeto (con la notación objeto.metodo()), this apunta al objeto que hay a la izquierda del punto:
const usuario = {
nombre: 'Ana',
saludar() {
console.log('Hola, soy ' + this.nombre);
}
};
usuario.saludar(); // "Hola, soy Ana"
// Si extraes el método, pierdes el contexto:
const fn = usuario.saludar;
fn(); // "Hola, soy undefined" (this = window/global)
this en funciones normales
Una función regular llamada directamente (no como método) tiene this igual al objeto global en modo no estricto, y undefined en modo estricto:
function mostrarThis() {
console.log(this);
}
mostrarThis(); // window (no estricto) / undefined (estricto)
'use strict';
function mostrarThisEstricto() {
console.log(this); // undefined
}
mostrarThisEstricto();
El bug clásico: perder this en callbacks
Este es el problema más frecuente con this. Al pasar un método como callback, se pierde el contexto del objeto:
const temporizador = {
segundos: 0,
iniciar() {
// Bug: this dentro del callback no es temporizador
setInterval(function() {
this.segundos++; // Error: this es window/undefined
console.log(this.segundos);
}, 1000);
}
};
// Solución 1: guardar referencia a this
const temporizador2 = {
segundos: 0,
iniciar() {
const self = this;
setInterval(function() {
self.segundos++;
console.log(self.segundos);
}, 1000);
}
};
// Solución 2: arrow function (hereda this del scope externo)
const temporizador3 = {
segundos: 0,
iniciar() {
setInterval(() => {
this.segundos++; // this es temporizador3
console.log(this.segundos);
}, 1000);
}
};
this con new
Cuando usas new con una función constructora o clase, this apunta al nuevo objeto que se está creando:
function Producto(nombre, precio) {
this.nombre = nombre;
this.precio = precio;
this.conIva = function() {
return this.precio * 1.21;
};
}
const libro = new Producto('JS Moderno', 30);
console.log(libro.nombre); // 'JS Moderno'
console.log(libro.conIva()); // 36.3
Arrow functions y this
Las funciones flecha no tienen su propio this: heredan el this del scope donde se definen (no donde se llaman). Esto las hace ideales para callbacks, pero las descarta como métodos de objeto o constructores:
const objeto = {
valor: 42,
// MAL: arrow function como método, this no es objeto
obtenerMal: () => this.valor, // undefined
// BIEN: function normal
obtenerBien: function() { return this.valor; } // 42
};
console.log(objeto.obtenerMal()); // undefined
console.log(objeto.obtenerBien()); // 42
La forma de determinar this en cualquier momento: mira a la izquierda del punto cuando se llama la función. Si no hay punto, es el global o undefined en modo estricto. Si hay new, es el nuevo objeto. Si es una arrow function, sube al scope donde fue definida.
