Metodi degli object JavaScript e this
Impara i metodi degli object JavaScript e la parola chiave this: definizione dei metodi, risoluzione di this, method borrowing con call/apply/bind, method chaining e arrow function.
Introduzione ai metodi degli object in JavaScript
Gli object JavaScript sono collezioni di proprietà, e i metodi degli object sono funzioni memorizzate come proprietà di quegli object. I metodi permettono a un object di fare cose con i propri dati, non solo di conservarli.
Questa guida spiega come definire e chiamare i metodi, come la parola chiave this collega un metodo al proprio object, come leggere e modificare lo stato dell'object dall'interno dei metodi, e l'errore più comune del linguaggio: perdere this nelle callback. Si conclude con la differenza pratica tra le funzioni normali e le arrow function.
Definire e chiamare i metodi
Un metodo è semplicemente una proprietà il cui valore è una funzione. La sintassi abbreviata greet() { ... } è il modo moderno di scriverlo; equivale a greet: function() { ... }.
greet è un metodo dell'object user. Usa this.name per accedere alla proprietà name dell'object, dimostrando come i metodi possano agire sui dati del proprio object. Si chiama un metodo con la stessa sintassi a punto usata per qualsiasi proprietà, seguita da (): user.greet().
La parola chiave this nei metodi
La parola chiave this fa riferimento all'object prima del punto nel momento in cui il metodo viene chiamato. Viene decisa al momento della chiamata, non quando la funzione è scritta — questo è ciò che rende this flessibile ma anche soggetto a errori.
Esempio: uso di this nei metodi
Nel metodo details, this viene usato per fare riferimento all'object person stesso, consentendo l'accesso alle proprietà name e age per produrre un messaggio personalizzato. Poiché details è stato chiamato come person.details(), this è person.
Modificare le proprietà dell'object
I metodi non servono solo per recuperare i valori delle proprietà, ma anche per aggiornarli.
Esempio: aggiornare le proprietà
Il metodo promote aggiorna la proprietà jobTitle e stampa un messaggio che riflette il cambiamento. Questo illustra come i metodi possano modificare dinamicamente lo stato interno di un object.
Usare i metodi per i calcoli
I metodi sono utili anche per eseguire calcoli basati sulle proprietà dell'object.
Esempio: calcolare valori
Il metodo area calcola l'area del rettangolo usando le proprietà width e height. Questo esempio mostra come i metodi possano incapsulare funzionalità che operano sui dati memorizzati all'interno di un object.
Borrowing dei metodi
Poiché this viene risolto al momento della chiamata, la stessa funzione può essere eseguita su object diversi. Questa è la base del method borrowing.
Esempio: borrowing di un metodo
Qui, il metodo speak dall'object dog viene assegnato all'object cat. Quando viene chiamato come cat.speak(), this.name fa riferimento a Whiskers, dimostrando che this dipende da come il metodo è chiamato, non da dove è stato definito.
Quando non puoi riassegnare il metodo ma vuoi comunque prenderlo in prestito, usa call, apply o bind per impostare this esplicitamente. Vedi Decoratori e forwarding, call/apply per la trattazione completa.
introduce.call(alice) esegue introduce con this impostato su alice, anche se introduce è una funzione standalone e non una proprietà di nessuno dei due object.
Method chaining
Il method chaining consente di chiamare più metodi in una singola espressione facendo restituire a ciascun metodo return this — l'object stesso. L'object restituito diventa il destinatario della chiamata successiva.
Esempio: implementare il method chaining
Ogni metodo in calculator modifica value e restituisce l'object, permettendo le chiamate concatenate. Questo pattern migliora la leggibilità ed è la base delle API fluenti come jQuery e molti helper sugli array.
Funzioni tradizionali vs. arrow function
In JavaScript, il comportamento della parola chiave this varia significativamente tra le funzioni tradizionali e le arrow function. Comprendere questa differenza è la cosa più importante per scrivere codice privo di bug che dipenda da this.
Presta sempre attenzione a this che perde il proprio contesto nelle callback o quando si passa un metodo come argomento. In questi casi this potrebbe non fare riferimento all'object di origine — potrebbe essere undefined (in strict mode / moduli) o l'object globale.
Funzioni tradizionali
In una funzione tradizionale, this è determinato da come viene chiamata la funzione. Ecco come varia:
- Contesto globale: quando una funzione viene chiamata senza un object prima del punto,
thisè l'object globale (windownei browser,globalin Node) nel codice non-strict, eundefinedin strict mode o nei moduli.
- Metodi di object: quando una funzione viene chiamata come metodo di un object,
thisfa riferimento a quell'object.
- Event handler: quando una funzione tradizionale è usata come event handler,
thisfa riferimento all'elemento che ha ricevuto l'evento.
<button id="myButton">Click me</button>
<p id="output">Click the button to see the result.</p>
<script>
document.getElementById("myButton").addEventListener("click", function () {
document.getElementById("output").innerHTML = "This button was clicked: " + this;
});
</script>Arrow function
Le arrow function non hanno un proprio this. Invece, catturano this dallo scope lessicale circostante nel momento in cui sono definite. Questo le rende ideali per le callback all'interno di un metodo, dove si vuole mantenere il this del metodo.
- Contesto coerente nelle callback: utile quando
thisdeve rimanere lo stesso all'interno di una callback annidata in un metodo.
Qui logActions usa una arrow function all'interno di forEach. La arrow function eredita this da logActions, quindi fa correttamente riferimento a userProfile.name. Una funzione tradizionale passata a forEach riceverebbe il proprio this (l'object globale o undefined), quindi this.name fallirebbe.
Non usare una arrow function per definire un metodo di un object di primo livello quando fai affidamento su this. Una arrow function non ha un proprio this, quindi eredita dallo scope circostante (spesso lo scope globale) invece che dall'object — this.name sarebbe undefined.
Esempio pratico
Usiamo un esempio realistico che coinvolge un object che gestisce il profilo online di un utente, dimostrando entrambi i tipi di funzione affiancati:
Questo esempio mostra chiaramente come le arrow function aiutino a mantenere il contesto corretto (this), specialmente nelle callback annidate dove il this dinamico di una funzione tradizionale fallirebbe silenziosamente.
Perdere this e come rimediare
Il bug classico: estrai un metodo in una variabile o lo passi come callback, e this non è più l'object.
Quando counter.show viene staccato, chiamare show() non ha alcun object prima del punto, quindi this viene perso. bind restituisce una nuova funzione il cui this è fissato in modo permanente. La stessa idea si applica a setTimeout(obj.method, 1000) (non funziona) rispetto a setTimeout(() => obj.method(), 1000) (funziona). Per un approfondimento, vedi Function binding.
Conclusione
I metodi degli object conferiscono un comportamento ai tuoi dati, e la parola chiave this è ciò che collega un metodo al proprio object. La regola fondamentale: this è l'object prima del punto al momento della chiamata, quindi può cambiare a seconda di come viene invocata una funzione. Le funzioni normali ottengono un this dinamico; le arrow function catturano this lessicalmente, il che è esattamente quello che si vuole per le callback ma sbagliato per i metodi di primo livello. Quando this viene perso, ricorri a bind, call o apply.
Per approfondire, esplora i riferimenti agli object e il comportamento di copia, le funzioni costruttore e new, e i decoratori con call/apply.