10. februar 2026

Objektmetoden, "this"

Objekter er normalt oprettet for at repræsentere enheder fra den virkelige verden, som brugere, ordrer og så videre:

let user = {
  name: "John",
  age: 30
};

Og i den virkelige verden kan en bruger handle: vælge noget fra indkøbskurven, logge ind, logge ud osv.

Handlinger repræsenteres i JavaScript ved funktioner i egenskaber.

Eksempler på metoder

Til at begynde med, lad os lære user at sige hej:

let user = {
  name: "John",
  age: 30
};

user.sayHi = function() {
  alert("Hej!");
};

user.sayHi(); // Hej!

Her har vi netop brugt et Funktionsudtryk til at oprette en funktion og tildele den til egenskaben user.sayHi af objektet.

Derefter kan vi kalde det som user.sayHi(). Brugeren kan nu tale!

En funktion, der er en egenskab af et objekt, kaldes dets metode.

Så her har vi en metode sayHi af objektet user.

Selvfølgelig kunne vi bruge en foruddefineret funktion som en metode, sådan her:

let user = {
  // ...
};

// først, deklarer
function sayHi() {
  alert("Hej!");
}

// så tilføj som en metode
user.sayHi = sayHi;

user.sayHi(); // Hej!
Objektorienteret programmering

Når vi skriver vores kode ved hjælp af objekter til at repræsentere enheder, kaldes det objektorienteret programmering, forkortet: “OOP”.

OOP er en stor ting, en interessant videnskab i sig selv. Hvordan vælger man de rigtige enheder? Hvordan organiserer man interaktionen mellem dem? Det er arkitektur, og der findes gode bøger om det emne, som “Design Patterns: Elements of Reusable Object-Oriented Software” af E. Gamma, R. Helm, R. Johnson, J. Vissides eller “Object-Oriented Analysis and Design with Applications” af G. Booch, og flere.

Metode ‘shorthand’

Der findes en kortere syntaks for metoder i et objektliteral:

// disse objekter gør det samme

user = {
  sayHi: function() {
    alert("Hej");
  }
};

// metode 'shorthand' ser bedre ud, ikke?
user = {
  sayHi() { // det samme som "sayHi: function(){...}"
    alert("Hej");
  }
};

Som du ser, kan vi udelade "function" og blot skrive sayHi().

For at være ærlig er noterne ikke helt identiske. Der er subtile forskelle relateret til objektarv (som vil blive dækket senere), men for nu betyder det ikke noget. I næsten alle tilfælde foretrækkes den kortere syntaks.

“this” i metoder

Det er almindeligt, at en objektmetode har brug for at få adgang til informationen, der er gemt i objektet, for at udføre sit arbejde.

For eksempel kan koden inde i user.sayHi() have brug for navnet på user.

For at få adgang til objektet kan en metode bruge nøgleordet this.

Værdien af this er objektet “før punktum”, det der bruges til at kalde metoden.

For eksempel:

let user = {
  name: "John",
  age: 30,

  sayHi() {
    // "this" er det "nuværende objekt"
    alert(this.name);
  }

};

user.sayHi(); // John

Under udførsel af user.sayHi(), vil værdien af this være user.

Teknisk set er det også muligt at få adgang til objektet uden this, ved at referere til det via den ydre variabel:

let user = {
  name: "John",
  age: 30,

  sayHi() {
    alert(user.name); // "user" i stedet for "this"
  }

};

…Men sådan kode er upålidelig. Hvis vi beslutter at kopiere user til en anden variabel, f.eks. admin = user og overskrive user med noget andet, så vil det få adgang til det forkerte objekt.

Det demonstreres nedenfor:

let user = {
  name: "John",
  age: 30,

  sayHi() {
    alert( user.name ); // fører til en fejl
  }

};


let admin = user;
user = null; // oveskriv for at gøre det tydeligt

admin.sayHi(); // TypeError: Cannot read property 'name' of null

Hvis vi brugte this.name i stedet for user.name inde i alert, så ville koden fungere.

“this” er ikke bundet

I JavaScript opfører nøgleordet this sig anderledes end i de fleste andre programmeringssprog. Det kan bruges i enhver funktion, selvom det ikke er en metode i et objekt.

Der er ingen syntaksfejl i følgende eksempel:

function sayHi() {
  alert( this.name );
}

Værdien af this evalueres under kørsel, afhængigt af konteksten.

For eksempel her er den samme funktion tildelt til to forskellige objekter og har forskellig “this” i kald:

let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
  alert( this.name );
}

// brug den samme funktion i to objekter
user.f = sayHi;
admin.f = sayHi;

// disse kald har forskellig this
// "this" inde i funktionen er objektet "før punktum"
user.f(); // John  (this == user)
admin.f(); // Admin  (this == admin)

admin['f'](); // Admin (adgang via dot eller firkantede parenteser til metoden – det er ligegyldigt)

Reglen er simpel: hvis obj.f() kaldes, så er this obj under kaldet af f. Så det er enten user eller admin i eksemplet ovenfor.

Kald uden et objekt: this == undefined

Vi kan endda kalde funktionen uden et objekt overhovedet:

function sayHi() {
  alert(this);
}

sayHi(); // undefined

I dette tilfælde er this undefined i strict mode. Hvis vi prøver at få adgang til this.name, vil der opstå en fejl.

I non-strict mode vil værdien af this i sådanne tilfælde være globalt objekt (window i en browser, vi kommer til det senere i kapitlet Objektet Global). Dette er en historisk adfærd, som "use strict" retter.

Normalt er sådan et kald en programmeringsfejl. Hvis der er this inde i en funktion, forventes det at blive kaldt i en objektkontekst.

Konsekvenserne af et ubundet this

Hvis du kommer fra et andet programmeringssprog, er du sandsynligvis vant til ideen om et “bundet this”, hvor metoder defineret i et objekt altid har this, der refererer til det objekt.

I JavaScript er this “frit”, dets værdi evalueres ved kaldetid og afhænger ikke af, hvor metoden blev erklæret, men snarere af hvilket objekt der er “før punktum”.

Konceptet med run-time evalueret this har både fordele og ulemper. På den ene side kan en funktion genbruges for forskellige objekter. På den anden side skaber den større fleksibilitet flere muligheder for fejl.

Her er vores holdning ikke at bedømme, om dette sprogdesign er godt eller dårligt. Vi vil forstå, hvordan man arbejder med det, hvordan man får fordele og undgår problemer.

Arrow funktioner har ikke deres eget “this”

Arrow funktioner er specielle: de har ikke deres eget this. Hvis vi refererer til this fra en sådan funktion, tages det fra den ydre “normale” funktion.

For eksempel her bruger arrow() this fra den ydre user.sayHi() metode:

let user = {
  firstName: "Karsten",
  sayHi() {
    let arrow = () => alert(this.firstName);
    arrow();
  }
};

user.sayHi(); // Karsten

Det er en speciel funktion ved arrow funktioner, det er nyttigt, når vi faktisk ikke ønsker at have et separat this, men snarere tage det fra den ydre kontekst. Senere i kapitlet Arrow funktioner genbesøgt vil vi gå mere i dybden med arrow funktioner.

Opsummering

  • Funktioner, der er gemt i objektets egenskaber, kaldes “metoder”.
  • Metoder tillader objekter at “handle” som objekt.doSomething().
  • Metoder kan referere til objektet som this.

Værdien af this defineres under kørsel.

  • Når en funktion erklæres, kan den bruge this, men det this har ingen værdi, før funktionen kaldes.
  • En funktion kan kopieres mellem objekter.
  • Når en funktion kaldes i “metode” syntaksen: objekt.metode(), er værdien af this under kaldet objekt.

Bemærk, at arrow funktioner er specielle: de har ikke deres eget this. Når this tilgås inde i en arrow funktion, tages det fra den ydre kontekst.

Opgaver

vigtighed: 5

Her returnerer funktionen makeUser et objekt.

Hvad er resultatet af at tilgå dets ref? Hvorfor?

function makeUser() {
  return {
    name: "John",
    ref: this
  };
}

let user = makeUser();

alert( user.ref.name ); // Hvad er resultatet?

Svar: en fejl.

Prøv det:

function makeUser() {
  return {
    name: "John",
    ref: this
  };
}

let user = makeUser();

alert( user.ref.name ); // Fejl: Kan ikke læse egenskaben 'name' af undefined

Dette sker fordi reglerne, der sætter this, ikke ser på objektdefinitionen. Kun øjeblikket for kaldet betyder noget.

Her er værdien af this inde i makeUser() undefined, fordi det kaldes som en funktion, ikke som en metode med “dot” syntaks.

Værdien af this er den samme for hele funktionen, kodeblokke og objektlitteraler påvirker det ikke.

ref: this tager faktisk den nuværende this fra funktionen.

Vi kan omskrive funktionen og returnere den samme this med værdien undefined:

function makeUser(){
  return this; // denne gang er der ikke noget object literal, så "this" er det samme som i funktionen
}

alert( makeUser().name ); // Fejl: Kan ikke læse egenskaben 'name' af undefined

Som du kan se, er resultatet af alert( makeUser().name ) det samme som resultatet af alert( user.ref.name ) fra det tidligere eksempel.

Her er det modsatte tilfælde:

function makeUser() {
  return {
    name: "John",
    ref() {
      return this;
    }
  };
}

let user = makeUser();

alert( user.ref().name ); // John

Nu virker det, fordi user.ref() er en metode. Og værdien af this sættes til objektet før punktum ..

vigtighed: 5

Opret et objekt calculator med tre metoder:

  • read() spørger efter to værdier og gemmer dem som egenskaber med navnene a og b.
  • sum() returnerer summen af de gemte værdier.
  • mul() multiplicerer de gemte værdier og returnerer resultatet.
let calculator = {
  // ... din kode ...
};

calculator.read();
alert( calculator.sum() );
alert( calculator.mul() );

Kør demoen

Åbn en sandbox med tests.

let calculator = {
  sum() {
    return this.a + this.b;
  },

  mul() {
    return this.a * this.b;
  },

  read() {
    this.a = +prompt('a?', 0);
    this.b = +prompt('b?', 0);
  }
};

calculator.read();
alert( calculator.sum() );
alert( calculator.mul() );

Åbn løsningen med tests i en sandbox.

vigtighed: 2

Der er et ladder objekt, der tillader dig at gå op og ned:

let ladder = {
  step: 0,
  up() {
    this.step++;
  },
  down() {
    this.step--;
  },
  showStep: function() { // viser det nuværende trin
    alert( this.step );
  }
};

Nu, hvis vi skal lave flere kald i rækkefølge, kan vi gøre det sådan her:

ladder.up();
ladder.up();
ladder.down();
ladder.showStep(); // 1
ladder.down();
ladder.showStep(); // 0

Modificer up, down og showStep metoderne, så kald kan kædes sammen, som dette:

ladder.up().up().down().showStep().down().showStep(); // viser 1 og derefter 0

Sådan en tilgang er bredt anvendt i JavaScript-biblioteker.

Åbn en sandbox med tests.

Løsningen er at returnere objektet selv fra hvert kald.

let ladder = {
  step: 0,
  up() {
    this.step++;
    return this;
  },
  down() {
    this.step--;
    return this;
  },
  showStep() {
    alert( this.step );
    return this;
  }
};

ladder.up().up().down().showStep().down().showStep(); // Viser 1 og derefter 0

Vi kan også skrive et enkelt kald per linje. For lange kæder er det mere læsbart:

ladder
  .up()
  .up()
  .down()
  .showStep() // 1
  .down()
  .showStep(); // 0

Åbn løsningen med tests i en sandbox.

Tutorial-oversigt

Kommentarer

læs dette før du kommenterer…
  • Hvis du har forslag til forbedringer - så opret venligst et GitHub-issue eller en pull request i stedet for at kommentere.
  • Hvis du ikke forstår noget i artiklen - så uddyb venligst.
  • For at indsætte få ord kode, brug <code>-taggen, for flere linjer - omslut dem i <pre>-tag, for mere end 10 linjer - brug en sandbox (plnkr, jsbin, codepen…)