La guida completa a questo in JavaScript

In JavaScript, ogni funzione ha un thisriferimento creato automaticamente quando lo dichiari.

JavaScript thisè abbastanza simile a un thisriferimento in altri linguaggi basati su classi come Java o C # (JavaScript è un linguaggio basato su prototipi e nessun concetto di "classe"): punta all'oggetto che sta chiamando la funzione (questo oggetto a volte chiamato come contesto ). In JavaScript, tuttavia, il thisriferimento all'interno delle funzioni può essere associato a oggetti diversi a seconda di dove viene chiamata la funzione .

Ecco 5 regole di base per l' thisassociazione in JavaScript:

Regola 1

Quando una funzione viene chiamata nell'ambito globale, il thisriferimento è associato per impostazione predefinita all'oggetto globale ( windownel browser o globalin Node.js). Per esempio:

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

Nota: se dichiari la foo()funzione sopra in modalità rigorosa, chiami questa funzione nell'ambito globale, thissarà undefinede l'assegnazione this.a = 2genererà Uncaught TypeErrorun'eccezione.

Regola 2

Esaminiamo l'esempio di seguito:

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

Chiaramente, nello snippet di cui sopra, la foo()funzione viene chiamata con il contesto è un objoggetto e il thisriferimento ora è vincolato obj. Quindi, quando una funzione viene chiamata con un oggetto contesto, il thisriferimento sarà associato a questo oggetto.

Regola 3

.call, .applyE .bindpossono essere utilizzati presso il sito chiamata esplicitamente bind this. L'uso .bind(this)è qualcosa che potresti vedere in parecchi componenti React.

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

Ecco un rapido esempio di come ciascuno di essi viene utilizzato per il binding this:

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

Regola 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

La cosa che devi notare è la Point2Dfunzione chiamata con newparola chiave e il thisriferimento è associato p1all'oggetto. Quindi, quando una funzione viene chiamata con la newparola chiave, creerà un nuovo oggetto e il thisriferimento sarà associato a questo oggetto.

Nota: quando chiamate una funzione con la newparola chiave, la chiamiamo anche come funzione di costruzione .

Regola 5

JavaScript determina il valore di thisin fase di esecuzione, in base al contesto corrente. Quindi a thisvolte può indicare qualcosa di diverso da quello che ti aspetti.

Considera questo esempio di una classe Cat con un metodo chiamato makeSound(), seguendo lo schema nella regola 4 (sopra) con una funzione di costruzione e la newparola chiave.

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

Ora proviamo a dare al gatto un modo per le annoy()persone ripetendo il suo suono 100 volte, una volta ogni mezzo secondo.

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();

Ciò non funziona perché all'interno del setIntervalcallback abbiamo creato un nuovo contesto con ambito globale, quindi thisnon punta più alla nostra istanza di kitty. In un browser web, thispunterà invece all'oggetto Window, che non ha un makeSound()metodo.

Un paio di modi per farlo funzionare:

  1. Prima di creare il nuovo contesto, assegnalo thisa una variabile locale chiamata me, o self, o come vuoi chiamarla, e usa quella variabile all'interno del callback.
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 è possibile evitare l'assegnazione thisa una variabile locale utilizzando una funzione freccia, che si lega thisal contesto del codice circostante in cui è definita.
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();