Cosa è "this" in una funzione JavaScript?
By Sergio Spina
- 3 minutes read - 527 wordsIl problema
Uno dei concetti più ripetuti e più accettati tra i programmatori JavaScript è che this
è un
costrutto difficile da capire, quasi esoterico. E in effetti i malintesi diffusi su questo argomento
sono tanti: che this
, chiamato all’interno di funzione, si riferisca alla funzione stessa, oppure
che si riferisca alla istanza cui la funzione-metodo appartiene.
Cerchiamo di capirci qualcosa in più.
L’ambito e il contesto
L’ambito di una funzione JavaScript (lo scope) è, da un punto di vista esteriore, tutto quello che c’è tra una parentesi graffa aperta e una chiusa. Dal punto di vista della struttura interna invece possiamo pensare all’ambito di una funzione come all’insieme di regole che definiscono il modo in cui vengono risolti i riferimenti alle variabili. È il lato statico del concetto di funzione, in quanto lo scope viene definito al momento in cui la funzione viene scritta, e rimane costante a prescindere dal luogo e dal momento in cui la funzione stessa viene chiamata.
Il contesto (o context) è invece l’oggetto che mette a disposizione della funzione le proprie proprietà di modo che la funzione possa accedervi quando è in esecuzione. È un concetto dinamico in quanto dipende da come viene chiamata la funzione, in quale momento, all’interno di quale oggetto.
Dunque una funzione JavaScript è, metaforicamente, una cellula costituita da una membrana che definisce uno spazio chiuso e immobile (l’ambito), all’interno del quale sono definite alcune variabili con le relative regole di accesso, che si muove dinamicamente all’interno di un corpo, il contesto, che mette a disposizione della funzione le proprietà con cui la funzione stessa può interagire.
this
è un riferimento al contesto
Orbene, this
è esattamente la via di dialogo tra lo scope e il context; è lo strumento di
comunicazione tra la funzione e ciò che è intorno a essa. In altre parole this
è il riferimento
al contesto.
Alcuni esempi
1function zoo(animal) {
2 return function speak() {
3 console.log(`${animal} says ${this.saying}`);
4 };
5}
6
7let foxSaying = zoo(fox);
8foxSaying(); // fox says undefined
La funzione zoo
restituisce una funzione, speak
, che viene assegnata a foxSaying
e che usa un
riferimento al contesto (this.saying
). Ma il contesto in questo caso non è definito, e neanche
esiste un oggetto globale (come ad es. window
) che metta a disposizione una proprietà saying
.
this.saying
perciò non può che essere undefined
.
1let animalSound = {
2 saying: 'grrr',
3 foxSaying: foxSaying,
4};
5
6animalSound.foxSaying(); // fox says grrr
Adesso la funzione foxSaying
trova un contesto cui è assegnata, l’oggetto animalSound
, che le
offre la proprietà saying
; all’interno di foxSaying
, quindi, this
è un riferimento a
animalSound
e this.saying
si risolve in “grrr”.
Un altro modo di assegnare un contesto a this
è con il metodo call
:
1let sleepingAnimal = {
2 saying: 'mphpfff',
3};
4
5foxSaying.call(sleepingAnimal); // fox says mphpfff
In conclusione
L’uso di this
all’interno di una funzione consente di accedere alle proprietà
dell’oggetto-contesto, quindi rende la stessa funzione utilizzabile in contesti diversi. È un modo
per definire un algoritmo una sola volta e riutilizzarlo con dati provenienti da oggetti anche non
prevedibili al momento della scrittura della funzione.
Nel banner: Niklaus Wirth, creatore del linguaggio Pascal.