Forstå JavaScript «dette» nøkkelordet

Hva betyr dette søkeordet i JavaScript? Og hvordan kan du bruke det praktisk i JavaScript-programmet ditt? Dette er noen av de vanlige spørsmålene nybegynnere og til og med noen erfarne JavaScript-utviklere stiller om dette nøkkelordet.

Hvis du er en av de utviklerne som lurer på hva dette søkeordet handler om, så er denne artikkelen for deg. Utforsk hva dette refererer til i forskjellige sammenhenger og gjør deg kjent med noen gotchas for å unngå forvirring, og selvfølgelig feil i koden din.

«dette» i det globale omfanget

I global kontekst vil dette returnere vindusobjektet så lenge det er utenfor en funksjon. Global kontekst betyr at du ikke plasserer den inne i en funksjon.

 if(true) {
  console.log(this)
}

let i = 2
while(i < 10) {
  console.log(this)
  i++
}

Hvis du kjører koden ovenfor, får du vindusobjektet.

«dette» innvendige funksjoner (metoder)

Når det brukes inne i funksjoner, refererer dette til objektet som funksjonen er bundet til. Unntaket er når du bruker dette i en frittstående funksjon, i så fall returnerer det vindusobjektet. La oss se noen eksempler.

I følgende eksempel er sayName-funksjonen inne i meg-objektet (dvs. det er en metode). I tilfeller som dette refererer dette til objektet som inneholder funksjonen.

  
function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley",
  sayName: sayName
}

console.log(me.sayName())

dette er meg-objektet, så å si this.name inne i sayName-metoden er nøyaktig det samme som me.name.

En annen måte å tenke på er at det som er på venstre side av funksjonen når den aktiveres, vil være dette. Dette betyr at du kan gjenbruke sayName-funksjonen i forskjellige objekter og denne vil referere til en helt annen kontekst hver gang.

  Slik fikser du at GIMP Eraser ikke fungerer

Nå, som tidligere nevnt, returnerer dette vindusobjektet når det brukes i en frittstående funksjon. Dette er fordi en frittstående funksjon er bundet til vindusobjektet som standard:

 function talk() {
  return this
}

talk()

Å kalle talk() er det samme som å kalle window.talk(), og alt som er på venstre side av funksjonen blir automatisk dette.

På en sidenotat, dette nøkkelordet i funksjonen oppfører seg annerledes i JavaScripts strenge modus (det returnerer udefinert). Dette er også noe å huske på når du bruker UI-biblioteker som bruker streng modus (f.eks. React).

Bruke «dette» med Function.bind()

Det kan være scenarier der du ikke bare kan legge til funksjonen til et objekt som en metode (som i den siste delen).

Kanskje objektet ikke er ditt, og du henter det fra et bibliotek. Objektet er uforanderlig, så du kan ikke bare endre det. I tilfeller som dette kan du fortsatt utføre funksjonssetningen separat fra objektet ved å bruke Function.bind()-metoden.

I det følgende eksempelet er ikke sayName-funksjonen en metode på me-objektet, men du har fortsatt bundet den ved å bruke bind()-funksjonen:

 function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley"
}

const meTalk = sayName.bind(me)

meTalk()

Uansett hvilket objekt du sender inn i bind() vil bli brukt som verdien av dette i det funksjonskallet.

Oppsummert kan du bruke bind() på hvilken som helst funksjon og sende i en ny kontekst (et objekt). Og det objektet vil overskrive betydningen av dette inne i den funksjonen.

  15 Python-prosjekter for nybegynnere å øve på og lære

Bruke «dette» med Function.call()

Hva om du ikke vil returnere en helt ny funksjon, men heller bare kalle funksjonen etter å ha bundet den til konteksten? Løsningen for det er call()-metoden:

 function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley"
}

sayName.call(me)

Call()-metoden utfører funksjonen umiddelbart i stedet for å returnere en annen funksjon.

Hvis funksjonen krever en parameter, kan du sende den via call()-metoden. I det følgende eksempelet sender du språket til sayName()-funksjonen, slik at du kan bruke den til å betinget returnere forskjellige meldinger:

 function sayName(lang) {
  if (lang === "en") {
    return `My name is ${this.name}`
  } else if (lang === "it") {
    return `Io sono ${this.name}`
  }
}

const me = {
  name: "Kingsley"
}

sayName.call(me, 'en')
sayName.call(me, 'it')

Som du kan se, kan du bare sende hvilken som helst parameter du vil til funksjonen som det andre argumentet til call()-metoden. Du kan også sende så mange parametere du vil.

Apply()-metoden er veldig lik call() og bind(). Den eneste forskjellen er at du sender flere argumenter ved å skille dem med et komma med call(), mens du sender flere argumenter inne i en matrise med application().

Oppsummert lar bind(), call() og apply() deg alle kalle funksjoner med et helt annet objekt uten å ha noen form for relasjon mellom de to (dvs. funksjonen er ikke en metode på objektet).

«dette» inne i konstruktørfunksjoner

Hvis du kaller en funksjon med et nytt nøkkelord, oppretter den et dette objektet og returnerer det:

 function person(name){
  this.name = name
}

const me = new person("Kingsley")
const her = new person("Sarah")
const him = new person("Jake")

me.name
her.name
him.name

I koden ovenfor opprettet du tre forskjellige objekter fra samme funksjon. Det nye nøkkelordet oppretter automatisk en binding mellom objektet som blir opprettet og dette nøkkelordet inne i funksjonen.

  10 verktøy for å lage et salgsdashbord [2023]

«dette» inne i tilbakeringingsfunksjoner

Tilbakeringingsfunksjoner er forskjellige fra vanlige funksjoner. Tilbakeringingsfunksjoner er funksjoner som du sender til en annen funksjon som et argument, slik at de kan utføres umiddelbart etter at hovedfunksjonen er ferdig utført.

Dette nøkkelordet refererer til en helt annen kontekst når det brukes i tilbakeringingsfunksjoner:

 function person(name){
  this.name = name
  setTimeout(function() {
    console.log(this)
  }, 1000)
}

const me = new person("Kingsley")

Etter ett sekund med å kalle personkonstruktørfunksjonen og opprette et nytt meg-objekt, vil den logge vindusobjektet som verdien av dette. Så når det brukes i en tilbakeringingsfunksjon, refererer dette til vindusobjektet og ikke det «konstruerte» objektet.

Det er to måter å fikse dette på. Den første metoden er å bruke bind() for å binde personfunksjonen til det nykonstruerte objektet:

 function person(name){
  this.name = name
  setTimeout(function() {
    console.log(this)
  }.bind(this), 1000)
}

const me = new person("Kingsley")

Med modifikasjonen ovenfor vil dette i tilbakekallingen peke på det samme som konstruktørfunksjonen (me-objektet).

Den andre måten å løse problemet med dette i tilbakeringingsfunksjoner er ved å bruke pilfunksjoner.

«dette» inne i pilfunksjoner

Pilfunksjoner er forskjellige fra vanlige funksjoner. Du kan gjøre tilbakeringingsfunksjonen til en pilfunksjon. Med pilfunksjoner trenger du ikke lenger bind() fordi den binder seg automatisk til det nykonstruerte objektet:

 function person(name){
  this.name = name
  setTimeout(() => {
    console.log(this)
  }, 1000)
}

const me = new person("Kingsley")

Lær mer om JavaScript

Du har lært alt om «dette» søkeordet og hva det betyr i alle de forskjellige sammenhengene i JavaScript. Hvis du er ny på JavaScript, vil du ha stor nytte av å lære alt det grunnleggende om JavaScript og hvordan det fungerer.