1

¿Conoces la palabra reservada "this"? Descubre por qué existe, cómo funciona y los métodos que te permitirán trabajar mejor con él

¿Qué es “this”?
El objeto <ins>contexto</ins> de JavaScript en el cual se está ejecutando el código actual (esto no dice mucho ahora, lo irás entendiendo a medida que vayas conociendo su comportamiento).

¿Por qué existe “this”?

  • Te permite decidir sobre qué objeto estará enfocada la invocación de una función o método.
  • Te permite re-utilizar funciones o métodos en diferentes contextos o con diferentes objetos.

¿A qué está haciendo referencia “this” cuando lo uso?
Esto lo puedes responder con ayuda de otra pregunta… ¿Dónde se invocó la función que usa “this”? ¡Hagámoslo simple! Piensa en “this” como un parámetro más de la función, cambiará de acuerdo a cómo la función sea llamada.

¿El método se llama a través de un objeto?

const persona = {
  nombre: 'Platzinauta',
  edad: 100,
  saludar() {
    alert(`Hola, mi nombre es ${this.nombre}`)
  }
}

persona.saludar() // Hola, mi nombre es Platzinauta

El “this” estará definido implícitamente, sólo hay que mirar a la izquierda del punto que llama al método para encontrar al objeto al que está haciendo referencia “this” (en este caso, persona).

¿Y si es un objeto literal complejo? ¡No importa! Aplica la misma regla (<ins>mirar lo que está inmediatamente a la izquierda del punto</ins>):

const persona = {
  nombre: 'Platzinauta',
  edad: 100,
  saludar() {
    alert(`Hola, mi nombre es ${this.nombre}`)
  },
  padre: {
    nombre: 'Freddy',
    saludar() {
      alert(`Hola, mi nombre es ${this.nombre}`)
    }
  }
}

persona.saludar() // Hola, mi nombre es Platzinauta
persona.padre.saludar() // Hola, mi nombre es Freddy

Y, ¿si es una función independiente que no está asociada a ningún objeto pero usa “this”?

functionsaludar(){
  alert(`Hola, mi nombre es ${this.nombre}`)
}

const persona = {
  nombre: 'Platzinauta',
  edad: 100,
}

En este caso, el “this” se debe referenciar explícitamente, haciendo uso del método de JavaScript call:

saludar.call(persona) // Hola, mi nombre es Platzinauta

Si la función saludar() recibiera parámetros, después de la referencia para “this” en los paréntesis de call se pueden pasar los parámetros:

saludar.call(persona, parametro1, parametro2, parametroN)

El método call de JavaScript tiene un hermano llamado apply; puedes usar uno u otro, pero si en algún momento tu función recibe un <ins>array como parámetro</ins>, apply recibe al array y lo descompondrá (mientras que call no puede recibir un array como parámetro, tocaría pasarle cada elemento de forma individual).

No quiero usar ni call ni apply, pero mi función tiene “this”, ¿qué puedo hacer?
¡No te preocupes! Hay un tercer método miembro de la familia llamado bind. A diferencia de sus hermanos, bind no invocará la función de inmediato, sino que te retornará una nueva para que la puedas invocar cuando quieras, con la referencia a “this” que tú elijas:

functionsaludar(){
  alert(`Hola, mi nombre es ${this.nombre}`)
}

const persona = {
  nombre: 'Platzinauta',
  edad: 100,
}

const saludoPlatzi = saludar.bind(persona) // Definimos que "this" hará referencia a "persona", y esa función se podrá ejecutar a través de "saludoPlatzi".

saludoPlatzi() // Hola, mi nombre es Platzinauta

OJO 👀 : Si tu función recibe un array como parámetro, la mejor opción es apply; si por alguna razón quieres usar call o bind, los elementos del array deberán pasarse uno a uno.

Pero, ¿qué pasa si defino una clase y creo instancias de esa clase, en vez de objetos literales?

classPersona{

  constructor(nombre, edad) {
    this.nombre = nombre
    this.edad = edad
  }

}

const platzinauta = new Persona('Platzinauta', 100)

La palabra reservada new definirá la referencia del “this”, a la instancia que se crea en cada sentencia.

¡Mucha información! 😑 No desesperes, no falta mucho más para que seas un experto en “this”…

¿Qué sucederá si llamo a la función y no uso ninguno de los métodos de la querida familia vista previamente? (call, apply, bind)
¡El “this” hará referencia al contexto donde se llama la función! Si la función está ahí, sola, como pan que no se vende 🍞, si no está dentro de una clase, o un objeto literal, o dentro de otra función, quiere decir que está en el contexto global, por lo que “this” hará referencia al objeto global, es decir, ¡<ins>window</ins>!

functiondecirEdad(){
  alert(`Hola, mi edad es ${this.edad}`)
}

const persona = {
  nombre: 'Platzinauta',
  edad: 100,
}

saludar()// Hola, mi edad es undefined

¿Undefined? ¿Por qué? Porque el objeto global window no tiene ningún atributo de edad 😄

Acaso, ¿se puede complicar más? ¡Si! Mentira, ¡no!… Solo hay un caso más, pero en vez de complicar las cosas, ayuda mucho a trabajar con “this”, y es el caso especial de las arrow functions ➡️. Si pasamos una función, como parámetro de otra función, el contexto de ejecución de la función pasada como parámetro será la función que la recibe, lo que muchas veces se traduce a la nada…

Para evitar que el contexto de la función parámetro sea el limbo, en vez de usar una función normal, podemos usar una arrow function ➡️, y la razón es muy sencilla, ¡<ins>las arrow functions no generan un nuevo contexto de ejecución</ins>! Por lo que, al pasar una arrow function como parámetro de otra función, el contexto de ejecución de la arrow function será el mismo de la función que la recibe como parámetro.

Ahora ya conoces todos los detalles de “this”, siéntete orgulloso de ti mismo por haber llegado hasta aquí, esto es algo que todo desarrollador de JavaScript debería conocer y entender.

Para terminar, te dejo este artículo de MDN, donde se exponen más detalles de “this”.

¡Saludos!

Escribe tu comentario
+ 2