Comprensione di questo, Bind, Call e Apply in JavaScript

Comprensione di questo, Bind, Call e Apply in JavaScript

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 thissenza 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.symbolall’interno dell’oggetto detailssi 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, thisfarà 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 thisma 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, come thisstesso sarebbe undefined.

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.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *