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 this
men 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 i
Uncaught 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 call
och 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.