JavaScript `this`: Komplett Guide for Nybegynnere og Eksperter

Hva innebærer egentlig nøkkelordet this i JavaScript? Hvordan kan du anvende det effektivt i dine JavaScript-prosjekter? Dette er spørsmål som ofte dukker opp hos både ferske og mer erfarne JavaScript-utviklere.

Hvis du er en utvikler som er nysgjerrig på this, er denne artikkelen skrevet for deg. Vi skal se nærmere på hva this refererer til i ulike situasjoner. Du vil også bli kjent med noen utfordringer som kan forårsake forvirring og feil i koden din.

this i globalt omfang

Når this brukes i globalt omfang, altså utenfor en funksjon, vil det referere til window-objektet. Globalt omfang betyr at koden ikke er plassert inne i en funksjonsblokk.

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

Kjører du denne koden, vil du se at det utskrives window-objektet.

this i funksjoner (metoder)

Når this benyttes i en funksjon, peker det vanligvis på objektet som funksjonen er tilknyttet. Unntaket er om funksjonen er frittstående; da refererer this til window-objektet. La oss illustrere dette med noen eksempler.

I det kommende eksemplet er siNavn-funksjonen en del av meg-objektet, noe som gjør den til en metode. I slike tilfeller vil this referere til objektet som inneholder metoden.

    function siNavn() {
      return `Mitt navn er ${this.navn}`;
    }
    const meg = {
      navn: "Kingsley",
      siNavn: siNavn
    };
    console.log(meg.siNavn());
  

Her vil this være meg-objektet. Dermed vil this.navn i siNavn-metoden være identisk med meg.navn.

Tenk på det som at det som står til venstre for funksjonen når den aktiveres, blir this. Dette åpner for at du kan bruke siNavn-funksjonen i forskjellige objekter, og this vil peke på en ny kontekst for hver gang.

Som nevnt tidligere, vil this referere til window-objektet når det brukes i en frittstående funksjon. Grunnen er at en frittstående funksjon er bundet til window-objektet som standard:

    function snakk() {
      return this;
    }
    snakk();
  

Å kalle snakk() er ekvivalent med å kalle window.snakk(), og det som står til venstre for funksjonen blir automatisk this.

Et viktig poeng: oppførselen til this-nøkkelordet endres i JavaScripts «strict mode» (den returnerer da undefined). Dette er noe å huske på dersom du bruker UI-biblioteker som benytter «strict mode» (som f.eks. React).

Bruk av this med Function.bind()

Det kan oppstå situasjoner der det ikke er mulig å bare legge til en funksjon som en metode i et objekt (som i forrige seksjon).

Det kan være at objektet ikke er ditt eget, men hentet fra et bibliotek. Eller at objektet er uforanderlig, slik at du ikke kan endre det. I slike tilfeller kan du bruke Function.bind()-metoden for å knytte en funksjon til et spesifikt objekt.

I eksemplet under er siNavn-funksjonen ikke en metode i meg-objektet, men den er bundet til det via bind()-funksjonen:

    function siNavn() {
      return `Mitt navn er ${this.navn}`;
    }
    const meg = {
      navn: "Kingsley"
    };
    const megSnakker = siNavn.bind(meg);
    megSnakker();
  

Uansett hvilket objekt du sender inn i bind(), vil det bli brukt som verdien til this i det påfølgende funksjonskallet.

Kort sagt kan bind() brukes på enhver funksjon for å knytte den til en ny kontekst (et objekt). Det spesifiserte objektet vil overstyre den vanlige betydningen av this inni funksjonen.

Bruk av this med Function.call()

Hva om du ikke ønsker å returnere en ny funksjon, men i stedet ønsker å kalle funksjonen umiddelbart etter at den er bundet til konteksten? Da er løsningen call()-metoden:

    function siNavn() {
      return `Mitt navn er ${this.navn}`;
    }
    const meg = {
      navn: "Kingsley"
    };
    siNavn.call(meg);
  

call()-metoden utfører funksjonen direkte, i motsetning til bind() som returnerer en ny funksjon.

Om funksjonen krever parametere, kan de sendes via call()-metoden. I eksemplet under sender vi språket til siNavn()-funksjonen, slik at vi betinget kan returnere ulike meldinger:

    function siNavn(lang) {
      if (lang === "no") {
        return `Mitt navn er ${this.navn}`;
      } else if (lang === "en") {
        return `My name is ${this.navn}`;
      }
    }
    const meg = {
      navn: "Kingsley"
    };
    siNavn.call(meg, 'no');
    siNavn.call(meg, 'en');
  

Som du ser, kan du sende inn de parameterne du måtte trenge som det andre argumentet (og påfølgende) til call()-metoden. Antall parametere er ikke begrenset.

apply()-metoden ligner veldig på call() og bind(). Hovedforskjellen er at call() tar parametere som separate argumenter, mens apply() mottar argumentene som en array.

For å oppsummere, bind(), call() og apply() gir deg alle mulighet til å kalle en funksjon med et helt annet objekt, uten at det er noen direkte relasjon mellom funksjonen og objektet (funksjonen trenger altså ikke å være en metode på objektet).

this i konstruktørfunksjoner

Dersom du kaller en funksjon med new-nøkkelordet, opprettes det et this-objekt og returneres:

    function person(navn) {
      this.navn = navn;
    }
    const meg = new person("Kingsley");
    const henne = new person("Sarah");
    const han = new person("Jake");
    meg.navn;
    henne.navn;
    han.navn;
  

I koden over har vi opprettet tre forskjellige objekter fra samme funksjon. new-nøkkelordet oppretter automatisk en kobling mellom det nye objektet og this-nøkkelordet inni funksjonen.

this i tilbakringingsfunksjoner

Tilbakringingsfunksjoner skiller seg fra vanlige funksjoner. Det er funksjoner som sendes til en annen funksjon som et argument, slik at de kan utføres når den første funksjonen er ferdig.

this-nøkkelordet kan referere til en annen kontekst når det brukes i tilbakringingsfunksjoner:

    function person(navn) {
      this.navn = navn;
      setTimeout(function() {
        console.log(this);
      }, 1000);
    }
    const meg = new person("Kingsley");
  

Etter ett sekund, etter at konstruktørfunksjonen person har blitt kalt og et nytt meg-objekt er opprettet, vil this logge window-objektet. Altså vil this, i en tilbakringingsfunksjon, referere til window-objektet og ikke det «konstruerte» objektet.

Det finnes to metoder for å løse dette. Den første er å bruke bind() for å knytte person-funksjonen til det nykonstruerte objektet:

    function person(navn) {
      this.navn = navn;
      setTimeout(function() {
        console.log(this);
      }.bind(this), 1000);
    }
    const meg = new person("Kingsley");
  

Med endringen over vil this i tilbakekallingen peke på det samme som i konstruktørfunksjonen (meg-objektet).

Den andre måten å løse problemet med this i tilbakringingsfunksjoner er ved hjelp av pilfunksjoner.

this i pilfunksjoner

Pilfunksjoner fungerer annerledes enn tradisjonelle funksjoner. Du kan endre en tilbakringingsfunksjon til en pilfunksjon. Med pilfunksjoner trenger du ikke lenger bind(), fordi de automatisk knyttes til det nykonstruerte objektet:

    function person(navn) {
      this.navn = navn;
      setTimeout(() => {
        console.log(this);
      }, 1000);
    }
    const meg = new person("Kingsley");
  

Utvid din JavaScript-kunnskap

Du har nå lært om this-nøkkelordet og hva det betyr i ulike sammenhenger i JavaScript. Hvis JavaScript er nytt for deg, vil du ha stor nytte av å lære det grunnleggende om JavaScript og hvordan det fungerer.