DEV Community

Cover image for ¿Qué es This en JavaScript?
gonzabarrera
gonzabarrera

Posted on • Updated on

¿Qué es This en JavaScript?

En general, el concepto de this, se aplica a una referencia a una instancia actual de la clase en la que aparece, esta referencia esta disponible en muchos lenguajes de programación, pero en el caso de javascript tiene algunas casuísticas más particulares.

Por regla general this es una referencia que se crea cuando una función que es invocada, y su valor depende de el lugar en el cual esta invocación se realice.

Ámbito Global

Si esta invocación no es llamada desde una función, this siempre hace referencia al objeto window

console.log(this);
Enter fullscreen mode Exit fullscreen mode
Window {window: Window, self: Window, …}
Enter fullscreen mode Exit fullscreen mode

Funciones

En el caso de las funciones, el valor de this, dependerá exclusivamente de el lugar en el cual esta es invocada.

por defecto, dentro de una función, this hace referencia al objeto global window

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

test();
Enter fullscreen mode Exit fullscreen mode
Window {window: Window, self: Window, …}
Enter fullscreen mode Exit fullscreen mode

Nuestro escenario cambia totalmente si usamos "use strict"

"use strict"

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

test();
Enter fullscreen mode Exit fullscreen mode
undefined
Enter fullscreen mode Exit fullscreen mode

El uso estricto nos ayuda a no modificar el ámbito global accidentalmente, por ejemplo:

function Cuadrado(ancho, alto) {
    this.ancho = 100;
    this.alto = 200;
}

const cuadrado = Cuadrado(50,60);
console.log(cuadrado); 
Enter fullscreen mode Exit fullscreen mode
undefined
Enter fullscreen mode Exit fullscreen mode

pero si vemos el valor de las variables dentro del objeto window

console.log(window.ancho,window.alto)
Enter fullscreen mode Exit fullscreen mode
100,200
Enter fullscreen mode Exit fullscreen mode

para prevenir esto, se necesita el uso de "use strict"

"use strict"
function Cuadrado(ancho, alto) {
    this.ancho = 100;
    this.alto = 200;
}

const cuadrado = Cuadrado(50,60);
console.log(cuadrado); 
Enter fullscreen mode Exit fullscreen mode
Uncaught TypeError: Cannot set property 'ancho' of undefined 
Enter fullscreen mode Exit fullscreen mode

no permitiendo modificar el valor de this en su ámbito local

En cambio, si agregamos a la declaración la palabra new, generamos una nueva instancia de this

"use strict"
function Cuadrado(ancho, alto) {
    this.ancho = 100;
    this.alto = 200;
}

const cuadrado = new Cuadrado(50,60);
console.log(cuadrado); 
Enter fullscreen mode Exit fullscreen mode
Object {
  alto: 200,
  ancho: 100
}
Enter fullscreen mode Exit fullscreen mode

Ahora si la invocación la realizamos en el constructor del objeto

"use strict"
function Cuadrado(ancho, alto) {
    this.ancho = ancho;
    this.alto = alto;
    console.log (this);
}

const cuadrado = new Cuadrado(50,60);
Enter fullscreen mode Exit fullscreen mode
Object {
  alto: 60,
  ancho: 50
}
Enter fullscreen mode Exit fullscreen mode

Métodos

Cuando llamamos a un método de una función, this se asocia al objeto que contiene dicho método

const cuadrado = {
    ancho: 100,
    alto: 200,
    info() {
        console.log('Soy un cuadrado de',this.ancho, 'x',this.alto);
        console.log(this);
    }
};
cuadrado.info();
Enter fullscreen mode Exit fullscreen mode
Soy un cuadrado de 100 x 200
Object {ancho: 100, alto: 200, info: ƒ...}
Enter fullscreen mode Exit fullscreen mode

Ahora todo cambiaría, si asignamos el método a una declaración de función

const cuadrado = {
    ancho: 100,
    alto: 200,
    info() {
        console.log('Soy un cuadrado de',this.ancho, 'x',this.alto);
        console.log(this);
    }
};
let mostrarInfo = cuadrado.info;
mostrarInfo();
Enter fullscreen mode Exit fullscreen mode
Soy un cuadrado de undefined x undefined
Window {window: Window, self: Window, …}
Enter fullscreen mode Exit fullscreen mode

Acá perdemos el contexto de this, ya que la llamada ocurre bajo el ámbito global

Arrow Functions

Al momento de crear un arrow function, el valor de this quedará asociado al valor de this de su ámbito externo

const test = () => {
    console.log(this);
};
test(); 
Enter fullscreen mode Exit fullscreen mode
Window {window: Window, self: Window, …}
Enter fullscreen mode Exit fullscreen mode

Antes de usar arrow functions, para poder manejar los valores del ámbito global dentro de métodos, debíamos usar un "hack" que era copiar el valor de this a otra variable

const cuadrado = {
  ancho: 100,
  agrandar() {
    const _this = this;
    setInterval(function () {
      console.log(++_this.ancho);
    }, 1000);
  }
};
cuadrado.agrandar();
Enter fullscreen mode Exit fullscreen mode

Solucionar esto con el uso de arrow function es mucho más limpio

const cuadrado = {
  ancho: 100,
  agrandar() {
    setInterval(() => {
      console.log(++this.ancho);
    }, 1000);
  }
};
cuadrado.agrandar();
Enter fullscreen mode Exit fullscreen mode

Bind

Existen adicionalmente, métodos que nos permiten modificar la referencia a donde apunta this

Veamos este ejemplo

const cuadrado = {
  ancho: 200,
  alto: 100,
  showDimensions: function() {
    return this.ancho + ' x ' + this.alto;
  }
}

const print = function() {
  console.log(this.showDimensions());
}

print();

Enter fullscreen mode Exit fullscreen mode
Uncaught TypeError: this.showDimensions is not a function
Enter fullscreen mode Exit fullscreen mode

this en la función print apunta a la referencia del objeto en el ámbito global, ergo no tiene acceso a showDimensions

En caso que necesitemos acceder al scope de cuadrado desde print necesitamos usar el método bind()

const printBinded = print.bind(cuadrado);
printBinded();
Enter fullscreen mode Exit fullscreen mode

De esta forma, le estamos diciendo que el valor de this en print, debe ser la referencia al de cuadrado

Call

La diferencia con Bind, es que este método, si ejecuta la función, igual que (), con la diferencia que Call tiene como parámetro la referencia de this en la función que se ejecuta.

const printBinded = print.bind(cuadrado);
printBinded();

Enter fullscreen mode Exit fullscreen mode

Con este obtendremos el mismo resultado que con Bind, con la diferencia que la función no se copia, si no que se ejecuta.

Apply

La diferencia entre Call y Apply, es tan solo la forma de enviar los parámetros, en el caso de apply esta orientado a recibir muchos parámetros, en forma de array

print.apply(cuadrado, ['100', '200']);
Enter fullscreen mode Exit fullscreen mode

Borrowing

Un préstamo de función es cuando compartimos la función de un objeto, pero con distintos parámetros


const cuadrado = {
  ancho: 100,
  alto: 200,
  showDimensions: function() {
    return this.ancho + ' x ' + this.alto;
  }
}

const rectangulo = {
  ancho: 500,
  alto: 200
}

const result = cuadrado.showDimensions.apply(rectangulo);
console.log(result); 
Enter fullscreen mode Exit fullscreen mode
500 x 200
Enter fullscreen mode Exit fullscreen mode

Currying

El concepto de currying es básicamente crear una copia de una función pero con parámetros por defecto

Ejemplo:

function showDimensions(a, b) {
  return a + ' x ' + b;
}

const showDimensionsCopy = showDimensions.bind(this, 200);

console.log(showDimensionsCopy(100));

Enter fullscreen mode Exit fullscreen mode
"200 x 100"
Enter fullscreen mode Exit fullscreen mode

cover picture by @bradstallcup

Top comments (0)