förstå detta, binda, ring och tillämpa i JavaScript

förstå detta, binda, ring och tillämpa i JavaScript

den här artikeln skrevs ursprungligen för DigitalOcean.

nyckelordetthis är ett mycket viktigt begrepp i JavaScript, och är också särskilt förvirrande för både nya utvecklare och de som har erfarenhet av andra programmeringsspråk. I JavaScript är this en referens till ett objekt., Objektet som this refererar till kan variera, implicit baserat på om det är globalt, på ett objekt eller i en konstruktör, och kan också variera explicit baserat på användningen av Function prototypmetoder bind, call och apply.

även om this är lite av ett komplext ämne, är det också ett som visas så snart du börjar skriva dina första JavaScript-program., Oavsett om du försöker komma åt ett element eller en händelse i Document Object Model (DOM), bygga klasser för att skriva i objektorienterad programmeringsstil, eller använda egenskaper och metoder för vanliga objekt, kommer du att stöta på this.

i den här artikeln lär du dig vad this hänvisar till implicit baserat på sammanhang, och du lär dig hur du använder metoderna bind, call och apply för att uttryckligen bestämma värdet på this. – herr talman!,

Implicit kontext

det finns fyra huvudkontexter där värdet påthis implicit kan härledas:

  • det globala sammanhanget
  • som en metod inom ett objekt
  • som konstruktör på en funktion eller klass
  • som en dom-händelsehanterare

Global

i det globala sammanhanget hänvisar this till det globala objektet. När du arbetar i en webbläsare är det globala sammanhanget window. När du arbetar i Node.js, det globala sammanhanget är global.,

Obs! Om du ännu inte är bekant med begreppet omfattning i JavaScript, läs förstående variabler, omfattning och lyftning i JavaScript.

för exemplen övar du koden i webbläsarens Developer Tools-konsol. Läs hur du använder JavaScript Developer Console om du inte är bekant med att köra JavaScript-kod i webbläsaren.

om du loggar värdet på this utan någon annan kod ser du vilket objekt this refererar till.,

console.log(this)
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}

Du kan se att this är window, vilket är det globala objektet i en webbläsare.

För att förstå variabler, omfattning och hissa i JavaScript lärde du dig att funktioner har sitt eget sammanhang för variabler. Du kan bli frestad att tro att this skulle följa samma regler i en funktion, men det gör det inte. En toppnivåfunktion behåller this referens för det globala objektet.,

Du skriver en toppnivåfunktion, eller en funktion som inte är associerad med något objekt, så här:

function printThis() { console.log(this)}printThis()

Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}

även inom en funktion hänvisar this fortfarande till window eller globalt objekt.

När du använder strikt läge kommer sammanhanget för this inom en funktion i det globala sammanhanget att vara undefined.,

'use strict'function printThis() { console.log(this)}printThis()
undefined

generellt är det säkrare att använda strikt läge för att minska sannolikheten för att this har en oväntad omfattning. Sällan vill någon hänvisa till objektetwindow medthis.

För mer information om strikt läge och vilka förändringar det gör när det gäller misstag och säkerhet, Läs strikt läge dokumentation på MDN.,

en Objektmetod

en metod är en funktion på ett objekt eller en uppgift som ett objekt kan utföra. En metod använderthis för att hänvisa till objektets egenskaper.

"The United States of America was founded in 1776."

i det här exemplet är this detsamma som america.

i ett kapslat objekt hänvisarthis till metodens aktuella objektomfattning. I följande exempel hänvisar this.symbol inom objektet details till details.symbol.,

"The symbol is the eagle and the currency is USD."

ett annat sätt att tänka på det är attthis refererar till objektet på vänster sida av pricken när man anropar en metod.

a Function Constructor

När du använder nyckelordet new skapar det en instans av en konstruktörsfunktion eller klass. Funktionskonstruktorer var det vanliga sättet att initiera ett användardefinierat objekt innan class-syntaxen introducerades i ECMAScript 2015-uppdateringen till JavaScript., För att förstå klasser i JavaScript lär du dig hur du skapar en funktionskonstruktor och en motsvarande klasskonstruktör.

"The United States of America was founded in 1776."

i detta sammanhang är this nu bunden till instansen av Country, som finns i konstanten america.

en Klasskonstruktör

en konstruktör på en klass fungerar som en konstruktör på en funktion. Läs mer om likheter och skillnader mellan funktionskonstruktorer och ES6 klasser för att förstå klasser i JavaScript.,

this I metodendescribe avser instansen avCountry, vilket äramerica.

"The United States of America was founded in 1776."

A Dom händelsehanterare

i webbläsaren finns ett specielltthis sammanhang för händelsehanterare. I en händelsehanterare som anropas av addEventListener hänvisar this till event.currentTarget., Oftare än inte, utvecklare kommer helt enkelt att använda event.target eller event.currentTarget som behövs för att komma åt element i DOM, men eftersom this referensändringar i detta sammanhang är det viktigt att veta.

i följande exempel skapar vi en knapp, lägger till text och lägger till den i DOM. När vi loggar värdet påthis inom händelsehanteraren kommer det att skriva ut målet.,

<button>Click me</button>

När du klistrar in det här i din webbläsare visas en knapp som läggs till på sidan som säger ”Klicka på mig”. Om du klickar på knappen ser du<button>Click me</button> visas i din konsol, eftersom du klickar på knappen loggar elementet, vilket är själva knappen. Som du kan se hänvisar this till det riktade elementet, vilket är det element vi lade till en händelseläsare till.,

Explicit sammanhang

i alla tidigare exempel bestämdes värdet påthis av dess sammanhang—oavsett om det är globalt, i ett objekt, i en konstruerad funktion eller klass, eller på en DOM-händelsehanterare. Men med call, apply eller bind kan du uttryckligen bestämma vad this ska referera till.,

det är svårt att definiera exakt när du ska använda call, apply, eller bind, eftersom det beror på sammanhanget för ditt program. bind kan vara särskilt användbart när du vill använda händelser för att komma åt egenskaper för en klass inom en annan klass. Om du till exempel skulle skriva ett enkelt spel kan du skilja användargränssnittet och i/O i en klass och spellogiken och ange i en annan., Eftersom spellogiken skulle behöva komma åt inmatning, till exempel knapptryckning och klick, skulle du vilja bind händelserna för att komma åt värdet this för spellogikklassen.

det viktiga är att veta hur man bestämmer vilket objektthis refererar till, vilket du kan göra implicit med vad du lärde dig i tidigare avsnitt, eller uttryckligen med de tre metoderna du kommer att lära dig nästa.,

ring och använd

call ochapply är mycket lika—de anropar en funktion med ett angivetthis sammanhang och valfria argument. Den enda skillnaden mellan call och apply är att call kräver att argumenten skickas i en efter en, och apply tar argumenten som en array.,

i det här exemplet skapar vi ett objekt och skapar en funktion som refererar till thismen har inget this – sammanhang.

"undefined was written by undefined"

eftersomsummary ochbook inte har någon anslutning, åberoparsummary I sig kommer endast att skriva utundefined, eftersom det Letar efter dessa egenskaper på det globala objektet.,

Obs! Om du försöker detta i strikt läge skulle det resultera iUncaught TypeError: Cannot read property 'title' of undefined, eftersomthis skulle varaundefined.

Du kan dock användacall ochapply för att aktiverathis – kontexten förbook på funktionen.,

summary.call(book)// or:summary.apply(book)
"Brave New World was written by Aldous Huxley."

det finns nu en koppling mellan book och summary när dessa metoder tillämpas. Låt oss bekräfta exakt vad this är.

function printThis() { console.log(this)}printThis.call(book)// or:whatIsThis.apply(book)
{title: "Brave New World", author: "Aldous Huxley"}

i det här fallet blir this faktiskt objektet som skickas som ett argument.

så här är calloch apply desamma, men det finns en liten skillnad., Förutom att kunna skickathis – sammanhanget som det första argumentet kan du också skicka ytterligare argument genom.

function longerSummary(genre, year) { console.log( `${this.title} was written by ${this.author}. It is a ${genre} novel written in ${year}.`, )}

medcall skickas varje ytterligare värde som du vill skicka som ett ytterligare argument.,

longerSummary.call(book, 'dystopian', 1932)
"Brave New World was written by Aldous Huxley. It is a dystopian novel written in 1932."

om du försöker skicka exakt samma argument med apply är detta vad som händer:

longerSummary.apply(book, 'dystopian', 1932)
Uncaught TypeError: CreateListFromArrayLike called on non-object at <anonymous>:1:15

för apply måste du skicka alla argument i en array.

longerSummary.apply(book, )
"Brave New World was written by Aldous Huxley. It is a dystopian novel written in 1932."

skillnaden mellan att skicka argumenten individuellt eller i en matris är subtil, men det är viktigt att vara medveten om., Det kan vara enklare och bekvämare att använda apply, eftersom det inte skulle kräva att funktionsanropet ändras om vissa parameterdetaljer ändras.

Bind

bådecall ochapply är engångsanvändningsmetoder-om du kallar metoden medthis—kontexten kommer den att ha den, men den ursprungliga funktionen kommer att förbli oförändrad.,

Ibland kan du behöva använda en metod om och om igen med this – kontexten för ett annat objekt, och i så fall kan du använda metoden bind för att skapa en helt ny funktion med en uttryckligen bunden this.

const braveNewWorldSummary = summary.bind(book)braveNewWorldSummary()
"Brave New World was written by Aldous Huxley"

i det här exemplet, varje gång du ringer braveNewWorldSummary, kommer det alltid att returnera det ursprungliga this värdet bundet till det., Om du försöker binda ett nytt this – sammanhang till det kommer det att misslyckas, så du kan alltid lita på att en bunden funktion returnerar värdet this som du förväntar dig.

även om det här exemplet försöker bindabraveNewWorldSummary igen behåller det ursprungligathis – sammanhanget från första gången det var bundet.

Pilfunktioner

Pilfunktioner har inte sina egnathis bindning. Istället går de upp till nästa nivå av utförande.,

det kan vara användbart att använda pilfunktionen i fall där du verkligen vill attthis ska hänvisa till det yttre sammanhanget. Om du till exempel hade en händelselyssnare inne i en klass skulle du förmodligen vilja att this hänvisar till ett visst värde i klassen.

i det här exemplet kommer du att skapa och lägga till knappen till DOM som tidigare, men klassen kommer att ha en händelseläsare som ändrar textvärdet på knappen när du klickar.

om du klickar på knappen ändras textinnehållet till värdet påbuttonText., Om du inte hade använt en pilfunktion här skulle this vara lika med event.currentTarget, och du skulle inte kunna använda den för att komma åt ett värde inom klassen utan att uttryckligen binda det. Denna taktik används ofta på klassmetoder i ramar som React.

slutsats

i den här artikeln lärde du dig omthis I JavaScript, och de många olika värden som den kan ha baserat på implicit runtime bindning, och explicit bindning genombind,call, ochapply., Du lärde dig också om hur bristen på this bindning i pilfunktioner kan användas för att referera till ett annat sammanhang. Med denna kunskap bör du kunna bestämma värdet påthis I dina program.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *