La guía completa para esto en JavaScript

En JavaScript, cada función tiene una thisreferencia creada automáticamente cuando la declaras.

JavaScript thises bastante similar a una thisreferencia en otros lenguajes basados ​​en clases como Java o C # (JavaScript es un lenguaje basado en prototipos y no tiene un concepto de "clase"): apunta al objeto que llama a la función (este objeto a veces se llama como contexto ). En JavaScript, sin embargo, la thisreferencia dentro de las funciones se puede vincular a diferentes objetos dependiendo de dónde se llame a la función .

Aquí hay 5 reglas básicas para la thisvinculación en JavaScript:

Regla 1

Cuando se llama a una función en el ámbito global, la thisreferencia está vinculada de forma predeterminada al objeto global ( windowen el navegador o globalen Node.js). Por ejemplo:

function foo() { this.a = 2; } foo(); console.log(a); // 2

Nota: Si declara la foo()función anterior en modo estricto, entonces llama a esta función en el alcance global, thisserá undefinedy la asignación this.a = 2arrojará una Uncaught TypeErrorexcepción.

Regla 2

Examinemos el ejemplo a continuación:

function foo() { this.a = 2; } const obj = { foo: foo }; obj.foo(); console.log(obj.a); // 2

Claramente, en el fragmento anterior, la foo()función se llama con el contexto es el objobjeto y la thisreferencia ahora está vinculada obj. Entonces, cuando se llama a una función con un objeto de contexto, la thisreferencia se vinculará a este objeto.

Regla 3

.call, .applyy .bindtodos se pueden usar en el sitio de la llamada para enlazar explícitamente this. El uso .bind(this)es algo que puede ver en muchos componentes de React.

const foo = function() { console.log(this.bar) } foo.call({ bar: 1 }) // 1

Aquí hay un ejemplo rápido de cómo se usa cada uno para enlazar this:

  • .call(): fn.call(thisObj, fnParam1, fnParam2)
  • .apply(): fn.apply(thisObj, [fnParam1, fnParam2])
  • .bind(): const newFn = fn.bind(thisObj, fnParam1, fnParam2)

Regla 4

function Point2D(x, y) { this.x = x; this.y = y; } const p1 = new Point2D(1, 2); console.log(p1.x); // 1 console.log(p1.y); // 2

Lo que debe notar es la Point2Dfunción llamada con la newpalabra clave, y la thisreferencia está vinculada al p1objeto. Entonces, cuando se llama a una función con una newpalabra clave, creará un nuevo objeto y la thisreferencia estará vinculada a este objeto.

Nota: Cuando llama a una función con newpalabra clave, también la llamamos como función constructora .

Regla 5

JavaScript determina el valor de thisen tiempo de ejecución, según el contexto actual. Entonces this, a veces puede apuntar a algo diferente de lo que espera.

Considere este ejemplo de una clase Cat con un método llamado makeSound(), siguiendo el patrón de la Regla 4 (arriba) con una función constructora y la newpalabra clave.

const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.makeSound(); // Fat Daddy says: Mrrooowww

Ahora intentemos darle al gato un camino a la annoy()gente repitiendo su sonido 100 veces, una vez cada medio segundo.

const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(function() { this.makeSound(); // <-- this line fails with `this.makeSound is not a function` count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();

Eso no funciona porque dentro de la setIntervaldevolución de llamada hemos creado un nuevo contexto con alcance global, por lo que thisya no apunta a nuestra instancia de kitty. En un navegador web, thisapuntará al objeto Window, que no tiene un makeSound()método.

Un par de formas de hacerlo funcionar:

  1. Antes de crear el nuevo contexto, asigne thisa una variable local llamada me, o self, o como quiera llamarlo, y use esa variable dentro de la devolución de llamada.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const self = this; const t = setInterval(function() { self.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();
  1. Con ES6 puede evitar la asignación thisa una variable local mediante el uso de una función de flecha, que se une thisal contexto del código circundante donde está definido.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(() => { this.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();