Frontend

A cosa serve il this in JavaScript?

Autore

Manuel Ricci

JavaScript, come linguaggio di programmazione versatile e potente, presenta numerosi concetti unici e interessanti. Uno di questi è la variabile this, che rappresenta uno degli aspetti più intriganti e talvolta confondenti di JavaScript. Comprendere this è essenziale per qualsiasi sviluppatore che desidera padroneggiare JavaScript, dato il suo ruolo cruciale nella scrittura di codice efficiente e nella comprensione del funzionamento interno del linguaggio.

Cos’è this in JavaScript?

La variabile this in JavaScript è un riferimento al contesto di esecuzione corrente. È importante notare che il valore di this non è fisso, ma cambia a seconda di come e dove viene chiamata una funzione.

In termini semplici, this si riferisce all'oggetto che sta "eseguendo" il codice corrente. Può riferirsi a diversi oggetti a seconda del contesto, come l'oggetto globale, l'oggetto di una classe, o l'oggetto che ha invocato una funzione.

this quindi cambia il suo valore in base al contesto dove si trova, ad esempio:

Nel contesto globale: In un contesto non strettamente definito (non in strict mode), this si riferisce all'oggetto globale, che è window nel browser e global in Node.js.

1  console.log(this === window); // true in un browser

All'interno di una funzione: Il valore di this all'interno di una funzione dipende da come la funzione viene chiamata. Se una funzione regolare è chiamata globalmente, this si riferisce ancora all'oggetto globale. In strict mode, tuttavia, this sarà undefined.

1  function mostraThis() {
2    console.log(this);
3  }
4  mostraThis(); // 'window' in non-strict mode, 'undefined' in strict mode

Metodi di oggetti: Quando this è usato all'interno di un metodo di un oggetto, si riferisce all'oggetto che contiene il metodo.

1  const oggetto = {
2    metodo: function() {
3      console.log(this);
4    }
5  };
6  oggetto.metodo(); // Logga `oggetto`

Confronto con Altri Linguaggi di Programmazione

In altri linguaggi di programmazione, come Java o C++, this ha un significato più statico e prevedibile, in quanto si riferisce sempre all'istanza della classe corrente. In JavaScript, tuttavia, a causa del suo modello di esecuzione basato su funzioni e della natura dinamica del linguaggio, this può avere significati diversi in base al contesto di chiamata.

this nelle arrow function e nelle funzioni regolari

Le funzioni regolari in JavaScript hanno un comportamento dinamico rispetto a this. Il valore di this all'interno di una funzione regolare dipende da come la funzione è chiamata, non da dove è definita.

Chiamata Diretta: Se una funzione regolare viene chiamata direttamente (ad esempio, funzione()), this fa riferimento all'oggetto globale (window in un browser, global in Node.js). In strict mode, this sarà undefined.

1  function funzioneRegolare() {
2    console.log(this);
3  }
4  funzioneRegolare(); // `window` in browser, `undefined` in strict mode

Come Metodo di un Oggetto: Se la funzione è un metodo di un oggetto, this si riferisce all'oggetto che contiene il metodo.

1  const oggetto = {
2    metodoRegolare: function() {
3      console.log(this);
4    }
5  };
6  oggetto.metodoRegolare(); // Logga `oggetto`

Arrow function

Le arrow function, introdotte in ES6, hanno un comportamento di this "lessicale". Ciò significa che this all'interno di una funzione arrow è sempre uguale a this nel contesto del codice circostante (dove la funzione è definita), indipendentemente da come la funzione è chiamata.

Ereditarietà Lessicale: Le funzioni arrow ereditano this dal loro contesto di definizione. Non hanno un proprio this.

1  const oggetto = {
2    metodoRegolare: function() {
3      const funzioneArrow = () => console.log(this);
4      funzioneArrow();
5    }
6  };
7  oggetto.metodoRegolare(); // Logga `oggetto`

In questo esempio, la funzioneArrow eredita this dal metodoRegolare.

Confronto e scenari di utilizzo

Preferire funzioni arrow per ereditare this: Le funzioni arrow sono utili quando si desidera mantenere il contesto di this dallo scope circostante, come in callback o in metodi definiti all'interno di altri metodi.

Usare funzioni regolari per un this dinamico: Le funzioni regolari sono più appropriate quando si ha bisogno che this faccia riferimento al contesto in cui la funzione è stata chiamata, come nei metodi degli oggetti.

Binding Esplicito di this

In JavaScript, è possibile impostare o "legare" esplicitamente il valore di this in una funzione. Questo si ottiene principalmente tramite tre metodi: .bind(), .call(), e .apply().

Metodo .bind()

Il metodo .bind() crea una nuova funzione che, quando viene chiamata, ha il suo this impostato al valore fornito. È utile per assicurarsi che this all'interno di una funzione sia legato a un oggetto specifico.

Esempio di .bind():

1  const oggetto = {
2    valore: 'Oggetto Originale',
3  };
4
5  function mostraThis() {
6    console.log(this.valore);
7  }
8
9  const legata = mostraThis.bind(oggetto);
10  legata(); // Logga 'Oggetto Originale'

In questo esempio, la funzione mostraThis viene legata a oggetto tramite .bind(), quindi quando legata viene chiamata, this si riferisce a oggetto.

Metodo .call()

Il metodo .call() chiama una funzione con un valore di this specificato e argomenti forniti individualmente. È utile per invocare una funzione e impostare esplicitamente il suo contesto this.

Esempio di .call():

1  function saluta(nome) {
2    console.log(`Ciao, ${nome}. Io sono ${this.valore}`);
3  }
4
5  const oggetto = {
6    valore: 'Oggetto con Call',
7  };
8
9  saluta.call(oggetto, 'Mario'); // Logga 'Ciao, Mario. Io sono Oggetto con Call'

Qui, saluta viene chiamata con this impostato su oggetto e l'argomento 'Mario'.

Metodo .apply()

Il metodo .apply() è simile a .call(), ma gli argomenti sono passati come un array, non singolarmente. È utile quando non si conosce il numero di argomenti in anticipo.

Esempio di .apply():

1  function somma(a, b) {
2    console.log(a + b + this.extra);
3  }
4
5  const oggetto = {
6    extra: 5,
7  };
8
9  somma.apply(oggetto, [1, 2]); // Logga 8 (1 + 2 + 5)

Qui, somma viene chiamata con this impostato su oggetto, e gli argomenti [1, 2].

Casi speciali e problemi comuni con this

Uno dei problemi più comuni nell'uso di this in JavaScript è la "perdita" del contesto. Questo avviene tipicamente quando una funzione che fa uso di this viene passata come callback.

Esempio di Perdita di Contesto:

1  const oggetto = {
2    nome: "Oggetto",
3    mostraNome: function() {
4      console.log(this.nome);
5    }
6  };
7
8  setTimeout(oggetto.mostraNome, 1000); // Logga 'undefined' invece di 'Oggetto'

In questo caso, la funzione mostraNome perde il suo contesto originale quando viene passata a setTimeout. this all'interno di mostraNome non si riferisce più a oggetto.

Uso di arrow functions per mantenere il contesto

Le funzioni arrow possono essere utilizzate per evitare la perdita di contesto, poiché catturano il valore di this dallo scope circostante al momento della loro definizione.

Esempio con Funzione Arrow:

1  const oggetto = {
2    nome: "Oggetto",
3    mostraNome: function() {
4      setTimeout(() => console.log(this.nome), 1000);
5    }
6  };
7
8  oggetto.mostraNome(); // Logga correttamente 'Oggetto'

Qui, la funzione arrow all'interno di setTimeout mantiene il contesto this originale di oggetto.

this in Event Listeners

Un'altra trappola comune si verifica con this negli event listeners. this all'interno di un listener si riferisce all'elemento che ha attivato l'evento, non all'oggetto che definisce il listener.

Esempio con Event Listener:

1  const oggetto = {
2    nome: "Oggetto",
3    init: function() {
4      document.addEventListener('click', function() {
5        console.log(this); // Si riferisce all'elemento `document`, non a `oggetto`
6      });
7    }
8  };

Per mantenere il contesto, si può utilizzare una funzione arrow o legare esplicitamente il contesto con .bind().

Uso di this in costruttori e classi

Nei costruttori e nelle classi, this si riferisce all'istanza dell'oggetto che viene creata. Tuttavia, se si dimentica di usare new con un costruttore, this può riferirsi inaspettatamente all'oggetto globale (o essere undefined in strict mode).

Esempio con Costruttore:

Il seguente esempio include l'uso di this in un contesto globale, all'interno di una funzione regolare, in un metodo di oggetto, e in una funzione arrow all'interno di un metodo di oggetto.

1// Contesto Globale
2console.log(this); // `this` si riferisce all'oggetto globale (es. `window` in un browser)
3
4// Funzione Regolare
5function mostraThisFunzione() {
6  console.log(this);
7}
8mostraThisFunzione(); // `this` si riferisce all'oggetto globale o `undefined` in strict mode
9
10// Oggetto con Metodo
11const oggetto = {
12  prop: "Valore Proprietà",
13  metodo: function() {
14    console.log(this.prop); // `this` si riferisce a `oggetto`
15    
16    // Funzione Arrow all'interno di un Metodo
17    const funzioneArrow = () => {
18      console.log(this.prop); // `this` qui eredita il contesto da `metodo`, quindi si riferisce ancora a `oggetto`
19    };
20    funzioneArrow();
21  }
22};
23
24oggetto.metodo();
25
26// Funzione Costruttore
27function Costruttore(valore) {
28  this.valore = valore;
29}
30
31const istanza = new Costruttore("Mio Valore");
32console.log(istanza.valore); // `this` all'interno del costruttore si riferisce a `istanza`
  1. Contesto Globale: Viene mostrato come this si riferisca all'oggetto globale.
  2. Funzione Regolare: Qui, this all'interno di una funzione regolare si riferisce all'oggetto globale o è undefined se in strict mode.
  3. Metodo di Oggetto: In un metodo di oggetto, this si riferisce all'oggetto che contiene il metodo.
  4. Funzione Arrow in Metodo: All'interno del metodo, una funzione arrow dimostra come essa erediti this dal suo contesto circostante.
  5. Funzione Costruttore: Un esempio di come this in una funzione costruttore si riferisce all'istanza dell'oggetto creato.

Caricamento...

Diventiamo amici di penna? ✒️

Iscriviti alla newsletter per ricevere una mail ogni paio di settimane con le ultime novità, gli ultimi approfondimenti e gli ultimi corsi gratuiti puubblicati. Ogni tanto potrei scrivere qualcosa di commerciale, ma solo se mi autorizzi, altrimenti non ti disturberò oltre.

Se non ti piace la newsletter ti ricordo la community su Discord, dove puoi chiedere aiuto, fare domande e condividere le tue esperienze (ma soprattutto scambiare due meme con me). Ti aspetto!

Ho in previsione di mandarti una newsletter ogni due settimane e una commerciale quando capita.