23. februar 2026

Function binding

Når vi videregiver objektmetoder som callbacks, for eksempel til setTimeout, opstår der et kendt problem: “vi mister this”.

I dette kapitel vil vi se de måder, hvorpå du kan fikse det.

Mister “this”

Vi har allerede set eksempler på, hvordan this går tabt. Når en metode videregives til et andet sted udenfor objektet går this tabt.

Her er hvordan det kan ske med setTimeout:

let user = {
  firstName: "Karsten",
  sayHi() {
    alert(`Hej, ${this.firstName}!`);
  }
};

setTimeout(user.sayHi, 1000); // Hej, undefined!

Som vi kan se, viser output’en ikke “Karsten” som this.firstName, men undefined!

Det er fordi setTimeout modtog funktionen user.sayHi seperaret fra objektet. Den sidste linje kan blive omskrevet som:

let f = user.sayHi;
setTimeout(f, 1000); // mistet user kontekst

Metoden setTimeout i browseren er lidt speciel: den sætter this=window for funktionskaldet (i Node.js bliverthis til et timer-objekt men det er mindre vigtigt her). Så med this.firstName kigger det efter window.firstName som ikke eksisterer. I andre lignende tilfælde vil this fremstå som undefined.

Opgaven er ret typisk – vi vil gerne videregive et objekts metode til et andet sted (her til en planlægger) hvor det så vil blive kaldt. Hvordan sikrer vi os at det vil blive kaldt med den rigtige kontekst?

Løsning 1: En wrapper

Den simple løsning er at bruge en wrapper-funktion:

let user = {
  firstName: "Karsten",
  sayHi() {
    alert(`Hej, ${this.firstName}!`);
  }
};

setTimeout(function() {
  user.sayHi(); // Hej, Karsten!
}, 1000);

Det virker fordi det modtager user fra det ydre leksikale miljø, og kalder metoden normalt.

Det samme, men kortere, kunne være:

setTimeout(() => user.sayHi(), 1000); // Hej, Karsten!

Virker fint, men der er en mindre sårbarhed i kodens struktur.

Hvad hvis user ændrer værdi før setTimeout udløses (der er en sekund forsinkelse!)? Så vil det pludselig kalde det forkerte objekt!

let user = {
  firstName: "Karsten",
  sayHi() {
    alert(`Hej, ${this.firstName}!`);
  }
};

setTimeout(() => user.sayHi(), 1000);

// ...værdien af user ændres inden der er gået et sekund
user = {
  sayHi() { alert("En anden user i setTimeout!"); }
};

// En anden user i setTimeout!

Den næste løsning garanterer, at sådan noget ikke vil ske.

Løsning 2: bind

Functioner leverer endnu en metode bind som tillader at fikse this.

Den grundlæggend syntaks er:

// der kommer en mere kompleks syntaks lidt senere
let boundFunc = func.bind(context);

Resultatet af func.bind(context) er et specielt funktion-lignende “eksotisk objekt”, som kan kaldes som en funktion og transparent overfører kaldet til func med this=context.

Med andre ord er et kald til boundFunc som et kald til func med et fastsat this.

For eksempel videregiver funcUser et kald til func med this=user:

let user = {
  firstName: "Karsten"
};

function func() {
  alert(this.firstName);
}

let funcUser = func.bind(user);
funcUser(); // Karsten

Her er func.bind(user) en “bundet variant” af func med et fastsat this=user.

Alle argumenter bliver videregivet til den originale func som de er, for eksempel:

let user = {
  firstName: "Karsten"
};

function func(phrase) {
  alert(phrase + ', ' + this.firstName);
}

// bind this til user
let funcUser = func.bind(user);

funcUser("Hej"); // Hej, Karsten (argument "Hej" videregives og this=user)

Lad os nu prøve med en metode fra et objekt:

let user = {
  firstName: "Karsten",
  sayHi() {
    alert(`Hej, ${this.firstName}!`);
  }
};

let sayHi = user.sayHi.bind(user); // (*)

// du kan køre det uden et objekt
sayHi(); // Hej, Karsten!

setTimeout(sayHi, 1000); // Hej, Karsten!

// selv hvis værdien af user ændres inden der er gået et sekund
// sayHi bruger den forud bundne værdi som referer til det gamle user-objekt
user = {
  sayHi() { alert("En anden user i setTimeout!"); }
};