Forstå JavaScript “dette” søgeord

Hvad betyder dette søgeord i JavaScript? Og hvordan kan du bruge det praktisk i dit JavaScript-program? Dette er nogle af de almindelige spørgsmål, som nybegyndere og endda nogle erfarne JavaScript-udviklere stiller om dette søgeord.

Hvis du er en af ​​de udviklere, der spekulerer på, hvad dette søgeord handler om, så er denne artikel noget for dig. Udforsk, hvad dette refererer til i forskellige sammenhænge, ​​og gør dig bekendt med nogle gotchas for at undgå forvirring, og selvfølgelig fejl i din kode.

“dette” Inde i Global Scope

I global sammenhæng vil dette returnere vinduesobjektet, så længe det er uden for en funktion. Global kontekst betyder, at du ikke placerer det inde i en funktion.

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

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

Hvis du kører ovenstående kode, får du vinduesobjektet.

“dette” indvendige funktioner (metoder)

Når det bruges inde i funktioner, refererer dette til det objekt, som funktionen er bundet til. Undtagelsen er, når du bruger dette i en selvstændig funktion, i hvilket tilfælde det returnerer vinduesobjektet. Lad os se nogle eksempler.

I det følgende eksempel er sayName-funktionen inde i mig-objektet (dvs. det er en metode). I tilfælde som dette refererer dette til det objekt, der indeholder funktionen.

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

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

console.log(me.sayName())

dette er mig-objektet, så at sige this.name inde i sayName-metoden er nøjagtig det samme som me.name.

En anden måde at tænke på er, at det, der er i venstre side af funktionen, når den aktiveres, vil være dette. Det betyder, at du kan genbruge sayName-funktionen i forskellige objekter, og dette vil referere til en helt anden kontekst hver gang.

Nu, som tidligere nævnt, returnerer dette vinduesobjektet, når det bruges i en selvstændig funktion. Dette skyldes, at en selvstændig funktion er bundet til vinduesobjektet som standard:

 function talk() {
  return this
}

talk()

At kalde talk() er det samme som at kalde window.talk(), og alt, der er i venstre side af funktionen, bliver automatisk til dette.

Som en sidebemærkning opfører dette nøgleord i funktionen sig anderledes i JavaScripts strenge tilstand (det returnerer udefineret). Dette er også noget, du skal huske på, når du bruger UI-biblioteker, der bruger streng tilstand (f.eks. React).

Brug af “dette” med Function.bind()

Der kan være scenarier, hvor du ikke bare kan tilføje funktionen til et objekt som en metode (som i sidste afsnit).

Måske er objektet ikke dit, og du trækker det fra et bibliotek. Objektet er uforanderligt, så du kan ikke bare ændre det. I tilfælde som dette kan du stadig udføre funktionssætningen separat fra objektet ved hjælp af Function.bind() metoden.

I det følgende eksempel er funktionen sayName ikke en metode på mig-objektet, men du har stadig bundet det ved hjælp af bind()-funktionen:

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

const me = {
  name: "Kingsley"
}

const meTalk = sayName.bind(me)

meTalk()

Uanset hvilket objekt du sender ind i bind() vil det blive brugt som værdien af ​​dette i det funktionskald.

Sammenfattende kan du bruge bind() på enhver funktion og sende i en ny kontekst (et objekt). Og det objekt vil overskrive betydningen af ​​dette inde i den funktion.

Brug af “dette” med Function.call()

Hvad hvis du ikke vil returnere en helt ny funktion, men hellere bare kalder funktionen efter at have bundet den til dens kontekst? Løsningen til det er call() metoden:

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

const me = {
  name: "Kingsley"
}

sayName.call(me)

Call()-metoden udfører straks funktionen i stedet for at returnere en anden funktion.

Hvis funktionen kræver en parameter, kan du sende den via call() metoden. I det følgende eksempel videregiver du sproget til sayName()-funktionen, så du kan bruge det til betinget at returnere forskellige meddelelser:

 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 en hvilken som helst parameter, du ønsker, til funktionen som det andet argument til call()-metoden. Du kan også sende så mange parametre som du vil.

Apply()-metoden ligner meget call() og bind(). Den eneste forskel er, at du sender flere argumenter ved at adskille dem med et komma med call(), mens du sender flere argumenter inde i et array med application().

Sammenfattende giver bind(), call() og apply() dig alle mulighed for at kalde funktioner med et helt andet objekt uden at have nogen form for relation mellem de to (dvs. funktionen er ikke en metode på objektet).

“dette” Inside Constructor-funktioner

Hvis du kalder en funktion med et nyt nøgleord, opretter den et dette objekt 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 ovenstående kode oprettede du tre forskellige objekter fra den samme funktion. Det nye nøgleord opretter automatisk en binding mellem det objekt, der oprettes, og dette nøgleord inde i funktionen.

“dette” inde i tilbagekaldsfunktioner

Tilbagekaldsfunktioner er forskellige fra almindelige funktioner. Tilbagekaldsfunktioner er funktioner, som du overfører til en anden funktion som et argument, så de kan udføres umiddelbart efter, at den primære er færdig med at udføre.

Dette nøgleord refererer til en helt anden kontekst, når det bruges i tilbagekaldsfunktioner:

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

const me = new person("Kingsley")

Efter et sekund med at have kaldt personkonstruktørfunktionen og oprettet et nyt mig-objekt, vil det logge vinduesobjektet som værdien af ​​dette. Så når det bruges i en tilbagekaldsfunktion, refererer dette til vinduesobjektet og ikke det “konstruerede” objekt.

Der er to måder at løse dette på. Den første metode bruger bind() til at binde personfunktionen til det nykonstruerede objekt:

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

const me = new person("Kingsley")

Med ovenstående modifikation vil dette i tilbagekaldet pege på det samme som konstruktorfunktionen (me-objektet).

Den anden måde at løse problemet med dette i tilbagekaldsfunktioner er ved at bruge pilefunktioner.

“dette” Inside Arrow-funktioner

Pilefunktioner er forskellige fra almindelige funktioner. Du kan gøre din tilbagekaldsfunktion til en pilefunktion. Med pilefunktioner behøver du ikke længere bind(), fordi den automatisk binder til det nykonstruerede objekt:

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

const me = new person("Kingsley")

Lær mere om JavaScript

Du har lært alt om “dette” søgeord og hvad det betyder i alle de forskellige sammenhænge i JavaScript. Hvis du er ny med JavaScript, vil du have stor gavn af at lære alt det grundlæggende om JavaScript, og hvordan det virker.