Javascript

This en JavaScript

This suele ser un tópico algo oscuro de JavaScript. En este post intento aclarar su uso y los diferentes valores que puede tener.

La palabra clave this en JavaScript devuelve un valor diferente según el contexto léxico en el que se encuentre.

Su valor puede variar según si JavaScript se encuentre en modo estricto o no.

Veamos el valor this en los diferentes contextos.

Contexto Global

En el contexto de ejecución global, this se refiere al objeto global. En el caso del navegador, este es el objeto window.

En la próxima version de ECMAScript 2021 ya existe una especificación para globalThis, una palabra clave que permitirá acceder al objeto global desde cualquier parte del código, sea en el navegador, como en Node.js.

Función

Dentro de una función, this devolverá el objeto global.

function devuelveGlobal () {
  return this;
}

devuelveGlobal() === window; // en el navegador esto devuelve true

En modo estricto, sin embargo, this en este contexto resulta undefined.

function devuelveGlobal () {
  'use strict';
  return this;
}

devuelveGlobal() === undefined; // true

Constructor

En una función constructor, this referencia al nuevo objeto en construcción.

function Libro (id, nombre) {
  this.id = id;
  this.nombre = nombre;
}

var libro = new Libro(1, 'Harry Potter y el prisionero de Azkaban');

console.log(libro.id); // 1
console.log(libro.nombre); // "Harry Potter y el prisionero de Azkaban"

La excepción a esta regla es cuando la función constructor retorne un objeto.

function Libro (id, nombre) {
  this.id = id;
  this.nombre = nombre;
  return {
    id: 2,
    nombre: 'Blade Runner'
  };
}

var libro = new Libro(1, 'Harry Potter y el prisionero de Azkaban');

console.log(libro.id); // 2
console.log(libro.nombre); // "Blade Runner"

Método de Objeto

Cuando una función es un método de un objeto, this hará referencia al objeto.

const cliente = {
  nombre: 'Juan',
  apellido: 'Perez',
  nombreCompleto: function () {
    return this.nombre + ' ' + this.apellido;
  }
}

console.log(cliente.nombreCompleto()); // "Juan Perez"

Manejadores de Eventos (Event Handlers)

En las funciones que manejan eventos, this devuelve el elemento que recibió el evento.

function manejarEvento () {
  return console.log(this);
}

document.getElementById('boton').addEventListener('click', manejarEvento);

<button id="boton">Clickeame</button>

Al clickear en el botón a consola va a imprimir el elemento clickeado.

javscript this output

Salida en consola al clickear el botón id="boton" en Google Chrome

Funciones Flecha (Arrow Functions)

A partir de ES6 JavaScript introdujo las funciones flecha. Este tipo de función no posee un valor propio de this, sino que mantiene el mismo valor del contexto léxico que la envuelve.

Veamos un ejemplo utilizando una función constructor:

function Mascota () {
  this.edad = 0; // aquí this es una instancia del objeto Mascota
  setInterval(function crecer () {
    this.edad++; // aquí this equivale al objeto global
  }, 1000);
}

El this dentro de setInterval devuelve un valor inesperado, diferente al this que lo precede. Previo a ES6, una solución común a este problema era la siguiente:

function Mascota () {
  var that = this;
  that.edad = 0;
  setInterval(function crecer () {
    that.edad++;
  }, 1000);
}

A partir de la introducción de la función flecha, el constructor del ejemplo quedaría así:

function Mascota () {
  this.edad = 0;
  setInterval(() => {
    // this mantiene la referencia a la instancia del objeto Mascota
    this.edad++;
  }, 1000);
}