Questo articolo è stato originariamente scritto per DigitalOcean.
La parola chiave this
è un concetto molto importante in JavaScript, e anche particolarmente confuso sia per i nuovi sviluppatori che per coloro che hanno esperienza in altri linguaggi di programmazione. In JavaScript, this
è un riferimento a un oggetto., L’oggetto this
si riferisce a può variare, in modo implicito base se è globale, su un oggetto o un costruttore, e può variare anche in modo esplicito l’utilizzo del tag Function
prototipo metodi bind
call
e apply
.
Sebbene this
sia un argomento un po ‘ complesso, è anche uno che appare non appena inizi a scrivere i tuoi primi programmi JavaScript., Sia che si stia tentando di accedere a un elemento o evento nel Document Object Model (DOM), creando classi per la scrittura nello stile di programmazione orientato agli oggetti o utilizzando le proprietà e i metodi degli oggetti regolari, si verificherà this
.
In questo articolo, imparerete che cosa this
si riferisce implicitamente, in base al contesto, e imparerete come utilizzare il tag bind
call
e apply
metodi per determinare esplicitamente il valore di this
.,
Contesto Implicito
Ci sono quattro principali contesti in cui il valore di this
può essere implicitamente dedotto:
- il contesto globale
- come un metodo all’interno di un oggetto
- come un costruttore su una funzione o una classe
- come DOM gestore di eventi
Mondiale
Nel contesto globale, this
si riferisce all’oggetto globale. Quando si lavora in un browser, il contesto globale è window
. Quando lavori nel Nodo.js, il contesto globale è global
.,
Nota: se non si ha ancora familiarità con il concetto di ambito in JavaScript, si prega di rivedere la comprensione delle variabili, l’ambito e il sollevamento in JavaScript.
Per gli esempi, si eserciterà il codice nella console degli strumenti di sviluppo del browser. Leggi Come utilizzare JavaScript Developer Console se non si ha familiarità con l’esecuzione di codice JavaScript nel browser.
Se registri il valore di this
senza alcun altro codice, vedrai a quale oggetto si riferisce this
.,
console.log(this)
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
Si può vedere che il this
è window
, che è l’oggetto globale di un browser.
Nella comprensione delle variabili, dell’ambito e del sollevamento in JavaScript, è stato appreso che le funzioni hanno il proprio contesto per le variabili. Potresti essere tentato di pensare chethis
seguirebbe le stesse regole all’interno di una funzione, ma non lo fa. Una funzione di livello superiore manterrà comunque il riferimentothis
dell’oggetto globale.,
scrivere una funzione di primo livello, o una funzione che non è associato con qualsiasi oggetto, come:
function printThis() { console.log(this)}printThis()
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
Anche all’interno di una funzione, this
fa ancora riferimento al window
o oggetto globale.
Tuttavia, quando si utilizza la modalità rigorosa, il contesto dithis
all’interno di una funzione sul contesto globale saràundefined
.,
'use strict'function printThis() { console.log(this)}printThis()
undefined
In generale, è più sicuro utilizzare la modalità strict per ridurre la probabilità che this
abbia un ambito imprevisto. Raramente qualcuno vorrà fare riferimento all’oggettowindow
usandothis
.
Per ulteriori informazioni sulla modalità strict e sulle modifiche apportate agli errori e alla sicurezza, leggere la documentazione sulla modalità Strict su MDN.,
Un metodo Oggetto
Un metodo è una funzione su un oggetto o un’attività che un oggetto può eseguire. Un metodo utilizza this
per fare riferimento alle proprietà dell’oggetto.
"The United States of America was founded in 1776."
In questo esempio,this
è lo stesso diamerica
.
In un oggetto nidificato, this
si riferisce all’ambito dell’oggetto corrente del metodo. Nell’esempio seguente, this.symbol
all’interno dell’oggetto details
si riferisce a details.symbol
.,
"The symbol is the eagle and the currency is USD."
Un altro modo di pensarci è chethis
si riferisce all’oggetto sul lato sinistro del punto quando si chiama un metodo.
Un costruttore di funzioni
Quando si utilizza la parola chiavenew
, viene creata un’istanza di una funzione o classe del costruttore. I costruttori di funzioni erano il modo standard per inizializzare un oggetto definito dall’utente prima che la sintassi class
fosse introdotta nell’aggiornamento ECMAScript 2015 a JavaScript., Nella comprensione delle classi in JavaScript, imparerai come creare un costruttore di funzioni e un costruttore di classi equivalente.
"The United States of America was founded in 1776."
In questo contesto, this
è ora associato all’istanza di Country
, che è contenuto nel tag america
costante.
Un costruttore di classe
Un costruttore su una classe agisce come un costruttore su una funzione. Ulteriori informazioni sulle somiglianze e le differenze tra costruttori di funzioni e classi ES6 nella comprensione delle classi in JavaScript.,
this
nel describe
metodo si riferisce all’istanza di Country
, che è america
.
"The United States of America was founded in 1776."
Un gestore di eventi DOM
Nel browser, c’è un contesto specialethis
per i gestori di eventi. In un gestore di eventi chiamato da addEventListener
, this
farà riferimento a event.currentTarget
., Il più delle volte, gli sviluppatori useranno semplicementeevent.target
oevent.currentTarget
come necessario per accedere agli elementi nel DOM, ma poiché ilthis
fa riferimento alle modifiche in questo contesto, è importante sapere.
Nel seguente esempio, creeremo un pulsante, aggiungeremo del testo e lo aggiungeremo al DOM. Quando registriamo il valore di this
all’interno del gestore eventi, stamperà il target.,
<button>Click me</button>
Una volta che si incolla questo nel browser, si vedrà un pulsante aggiunto alla pagina che dice “Click me”. Se si fa clic sul pulsante, verrà visualizzato<button>Click me</button>
nella console, poiché facendo clic sul pulsante si registra l’elemento, che è il pulsante stesso. Pertanto, come puoi vedere, this
si riferisce all’elemento mirato, che è l’elemento a cui abbiamo aggiunto un listener di eventi.,
Contesto esplicito
In tutti gli esempi precedenti, il valore dithis
è stato determinato dal suo contesto—se è globale, in un oggetto, in una funzione o classe costruita o su un gestore di eventi DOM. Tuttavia, utilizzandocall
,apply
, obind
, è possibile determinare esplicitamente a cosa deve fare riferimentothis
.,
È difficile definire esattamente quando usare call
, apply
, o bind
, poiché dipenderà dal contesto del tuo programma. bind
può essere particolarmente utile quando si desidera utilizzare gli eventi per accedere alle proprietà di una classe all’interno di un’altra classe. Ad esempio, se si dovesse scrivere un gioco semplice, è possibile separare l’interfaccia utente e I/O in una classe e la logica e lo stato del gioco in un’altra., Poiché la logica di gioco avrebbe bisogno di accedere all’input, come premere il tasto e fare clic, si vorrebbe bind
gli eventi per accedere al this
valore della classe logica di gioco.
La parte importante è sapere come determinare a quale oggetto si riferiscethis
, che puoi fare implicitamente con ciò che hai imparato nelle sezioni precedenti, o esplicitamente con i tre metodi che imparerai dopo.,
Chiama e applica
call
eapply
sono molto simili: invocano una funzione con un contestothis
specificato e argomenti opzionali. L’unica differenza tra call
e apply
è che call
richiede che gli argomenti vengano passati uno per uno e apply
prende gli argomenti come un array.,
In questo esempio, creeremo un oggetto e creeremo una funzione che fa riferimento a this
ma non ha this
contesto.
"undefined was written by undefined"
Dal summary
e book
non hanno alcun collegamento, invocando summary
dalla stessa stampa undefined
, come si guarda per le proprietà sull’oggetto globale.,
Nota: Tentare questa operazione in modalità rigorosa risulterebbe in
Uncaught TypeError: Cannot read property 'title' of undefined
, comethis
stesso sarebbeundefined
.
Tuttavia, è possibile utilizzare call
e apply
per richiamare il this
contesto book
sulla funzione.,
summary.call(book)// or:summary.apply(book)
"Brave New World was written by Aldous Huxley."
ora C’è una connessione tra book
e summary
quando questi metodi sono applicati. Confermiamo esattamente cosa èthis
.
function printThis() { console.log(this)}printThis.call(book)// or:whatIsThis.apply(book)
{title: "Brave New World", author: "Aldous Huxley"}
In questo caso, this
diventa effettivamente l’oggetto passato come argomento.
Ecco come call
e apply
sono gli stessi, ma c’è una piccola differenza., Oltre ad essere in grado di passare il contesto this
come primo argomento, è anche possibile passare argomenti aggiuntivi.
function longerSummary(genre, year) { console.log( `${this.title} was written by ${this.author}. It is a ${genre} novel written in ${year}.`, )}
Concall
ogni valore aggiuntivo che si desidera passare viene inviato come argomento aggiuntivo.,
longerSummary.call(book, 'dystopian', 1932)
"Brave New World was written by Aldous Huxley. It is a dystopian novel written in 1932."
Se si tenta di inviare l’esatto stessi argomenti con apply
questo è quello che succede:
longerSummary.apply(book, 'dystopian', 1932)
Uncaught TypeError: CreateListFromArrayLike called on non-object at <anonymous>:1:15
Invece di apply
, è necessario passare tutti gli argomenti in un array.
longerSummary.apply(book, )
"Brave New World was written by Aldous Huxley. It is a dystopian novel written in 1932."
La differenza tra passare gli argomenti singolarmente o in un array è sottile, ma è importante essere consapevoli., Potrebbe essere più semplice e più conveniente usare apply
, poiché non richiederebbe la modifica della chiamata di funzione se alcuni dettagli dei parametri cambiassero.
Bind
Entrambicall
eapply
sono metodi di utilizzo una tantum-se si chiama il metodo con il contestothis
lo avrà, ma la funzione originale rimarrà invariata.,
a Volte, potrebbe essere necessario utilizzare un metodo più con il this
contesto di un altro oggetto, e in questo caso si potrebbe usare il bind
metodo per creare una nuova funzione con un legato esplicitamente this
.
const braveNewWorldSummary = summary.bind(book)braveNewWorldSummary()
"Brave New World was written by Aldous Huxley"
In questo esempio, ogni volta che si chiama braveNewWorldSummary
, verrà sempre restituito l’originale this
valore associato., Il tentativo di associare un nuovo contesto this
ad esso fallirà, quindi puoi sempre fidarti di una funzione associata per restituire il valore this
che ti aspetti.
Anche se questo esempio tenta di associare nuovamentebraveNewWorldSummary
, mantiene il contesto originalethis
dalla prima volta che è stato associato.
Funzioni freccia
Le funzioni freccia non hanno il propriothis
binding. Invece, salgono al livello successivo di esecuzione.,
Può essere utile usare la funzione freccia nei casi in cui si desidera veramentethis
per fare riferimento al contesto esterno. Ad esempio, se hai un listener di eventi all’interno di una classe, probabilmente vorresti this
per fare riferimento a qualche valore nella classe.
In questo esempio, creerai e aggiungerai il pulsante al DOM come prima, ma la classe avrà un listener di eventi che cambierà il valore del testo del pulsante quando si fa clic.
Se si fa clic sul pulsante, il contenuto del testo cambierà al valore dibuttonText
., Se non avessi usato una funzione freccia qui,this
sarebbe uguale aevent.currentTarget
, e non saresti in grado di usarlo per accedere a un valore all’interno della classe senza legarlo esplicitamente. Questa tattica viene spesso utilizzata sui metodi di classe in framework come React.
Conclusione
In questo articolo, hai imparato su this
in JavaScript, e i numerosi e diversi valori potrebbe avere in base implicita runtime associazione e associazione esplicita attraverso il bind
call
e apply
., Hai anche imparato come la mancanza di this
binding nelle funzioni freccia può essere utilizzata per fare riferimento a un contesto diverso. Con questa conoscenza, dovresti essere in grado di determinare il valore di this
nei tuoi programmi.