Mit bind, call und apply den Kontext in JavaScript meistern
About 3 min reading time
In meinem letzten Beitrag habe ich bewusst noch ein paar Dinge unterschlagen, die im Umgang mit this
hilfreich sein können: bind
, apply
und call
. Zum einen war der Artikel schon gefühlt lang genug und außerdem nutze ich die drei Methoden (so gut wie) nie. Da mich Tobias aber darauf hingewiesen hat, hole ich das Ganze hier nach.
Einer Methode einen Context zuweisen, mit bind
Bisher habe ich, wenn ich einer Funktion einen Kontext mitgeben wollen, ein wenig geschummelt. In meinem letzten Artikel habe ich this
in einer anderen Variable gespeichert und diese dann in der Funktion genutzt.
Sehen wir uns das Beispiel aus dem letzten Artikel nochmal mit einer kleinen Veränderung an und versuchen dann, ohne that
zu arbeiten:
const john = {
lyrics: 'Let is be, let it be',
sing() {
console.log(this.lyrics);
},
singLater() {
const that = this;
setTimeout(function () {
that.sing();
}, 1);
}
};
john.singLater(); // 🎵 Let is be, let it be
Mithilfe von bind
erstellen wir nun eine neue Variable singWithContext
und binden in dieser den aktuellen Kontext (this
, was hier john
ist) an die Funktion sing
.
const john = {
lyrics: 'Let is be, let it be',
sing() {
console.log(this.lyrics);
},
singLater() {
const singWithContext = this.sing.bind(this);
setTimeout(function () {
singWithContext();
}, 1);
}
};
john.singLater(); // 🎵 Let is be, let it be
Das geht auch noch etwas kürzer:
const john = {
lyrics: 'Let is be, let it be',
sing() {
console.log(this.lyrics);
},
singLater() {
const singWithContext = this.sing.bind(this);
setTimeout(singWithContext, 1);
}
};
john.singLater(); // 🎵 Let is be, let it be
Man kann bind
auch noch nutzen, um sich Methoden von anderen Objekten zu „borgen“: Nehmen wir einmal das folgende Beispiel:
const farin = {
firstName: 'Farin',
lastName: 'Urlaub',
fullName: function () {
return `${this.firstName} ${this.lastName}`;
}
};
const bela = {
firstName: 'Bela B',
lastName: 'Felsenheimer'
};
console.log(farin.fullName()); // Farin Urlaub
Mittels bind
können wir jetzt den Kontext von Farins fullName()
ändern, um auch den Namen von Bela B auszugeben
const farin = {
firstName: 'Farin',
lastName: 'Urlaub',
fullName: function () {
return `${this.firstName} ${this.lastName}`;
}
};
const bela = {
firstName: 'Bela B',
lastName: 'Felsenheimer'
};
console.log(farin.fullName()); // Farin Urlaub
const belaBFullName = farin.fullName.bind(bela);
console.log(belaBFullName()); // Bela B Felsenheimer
An einem unbekannten Ort ruft jemand jetzt wahrscheinlich: "Das geht auch mit Vererbung!" und diese Person hat auch mehr oder weniger Recht. Wir nutzen hier aber JavaScript und damit eine (halbwegs) funktionale Programmiersprache und diese bietet uns halt Wege, die in anderen Programmiersprachen so nicht existieren.
apply und call
Jetzt ist es stellenweise auch etwas umständlich, die mit bind
an einen Kontext gebundene Funktion immer in einer Variable speichern zu müssen.
const rod = {
firstName: 'Rod',
lastName: 'Gonzales'
};
function sing(lyrics) {
console.log(`${this.firstName} ${this.lastName}: ${lyrics}`);
}
const rodSings = sing.bind(rod);
rodSings('Das sind Dinge, von denen ich gar nichts wissen will'); // 🎵 Rod Gonzales: Das sind Dinge, von denen ich gar nichts wissen will
Mit apply
und call
können wir das etwas verkürzen
const rod = {
firstName: 'Rod',
lastName: 'Gonzales'
};
function sing(lyrics) {
console.log(`${this.firstName} ${this.lastName}: ${lyrics}`);
}
sing.call(rod, 'Das sind Dinge, von denen ich gar nichts wissen will'); // 🎵 Rod Gonzales: Das sind Dinge, von denen ich gar nichts wissen will
Bei call
geben wir erst den Kontext an und dann alle Parameter, mit denen wir die Funktion aufrufen wollen.
const rod = {
firstName: 'Rod',
lastName: 'Gonzales'
};
function sing(lyrics) {
return console.log(`${this.firstName} ${this.lastName}: ${lyrics}`);
}
sing.apply(rod, ['Das sind Dinge, von denen ich gar nichts wissen will']); // 🎵 Rod Gonzales: Das sind Dinge, von denen ich gar nichts wissen will
Der Unterschied zu apply
ist minimal: apply
erwartet als zweiten Parameter einen Array, der alle Parameter für einen Aufruf enthält.
Mit bind
, apply
und call
, haben wir drei Möglichkeiten, den Kontext einer Funktion zu manipulieren. Das ist definitiv einfacher zu lesen als Hilfsvariablen wie that
oder self
zu nutzen. Ich selbst nutze die drei aber, wie erwähnt, selten. Dies liegt wahrscheinlich daran, dass ich eher funktional programmiere und Objekte bei mir meistens nur Daten enthalten.
Wie sieht Eure Erfahrung hier aus? Schlagt ihr Euch mit dem Kontext in Euren Programmen herum und setzt bind
, apply
und call
ein oder geht es Euch wie mir? Schreibt mir gerne auf Mastodon.