Unterschied zwischen apply(), call() und bind() in Javascript

Das Problem mit "this"

Wer zuerst eine andere Programmiersprache gelernt hat als Javascript dem sollte die Eigenart von "this" aufgefallen sein. Das "this" in Javascript ist nicht zu verwechseln mit "this" in Java oder PHP.

Im PHP ist "$this" stets eine Referenz auf das Objekt zu welchem es gehört. Im Javascript dagegen ist es eine Referenz auf den Kontext im dem die Funktion aufgerufen wird. Im klartext: "this" im Javascript hängt immer davon ab "wo" und "wie" die Funktion aufgerufen wird. Dazu kommt noch im welcher Umgebung wird der Code ausgeführt? Node.js oder Browser? Im strict mode oder ohne?

Hier ein kleines Beispiel:

// Globale "name" Variable
var name = "Tom Global";
 
// "name" Variable im user Scope
var user = {
     
    name: "Tom Scope",
     
    getName: function(){
 
        return this.name;
     
    }
}
 
/**
 * Wir erstellen eine Referenz zu user.getName
 * refGetName befindet sich im selben
 * Kontext wie " var name = 'Tom Global' "
 */
 
var refGetName = user.getName; //referenz
  
/**
 * Wenn wir refGetName aufrufen
 * bekommen wir als Ergebnis "Tom Global"
 * Im strict mode & node.js bekommen wir ein undefined!
 */
 
refGetName() // Tom Global
 
/**
 * Wenn wir user.getName() direkt aufrufen bekommen wir
 * Tom scope als Ergebnis
 */
 
user.getName() // Tom Scope

Abhilfe schaffen mit bind()

Jede Funktion besitzt eine bind() Methode. Mit dieser können wir unserer Funktion einen neuen Kontext zuweisen.

var name = "Tom Global";
 
var context1 = {
    name: "Tom Context1"
}
 
var context2 = {
    name: "Tom Context2"
}
 
var user = {
     
    name: "Tom Scope",
     
    getName: function(){
 
        return this.name;
     
    }
}
 
/**
 * Mithilfe von bind() können wir der getName Funktion
 * einen beliebigen Kontext zuweisen.
 */
var c1 = user.getName.bind(context1);
var c2 = user.getName.bind(context2);
var self = user.getName.bind(user);
var global = user.getName.bind(this);
             
console.log( c1() ); // Tom Context1
console.log( c2() ); // Tom Context2
console.log( self() ); // Tom Scope
console.log( global() ); // Tom Global oder undefined

Kurze Erklärung zu bind() Methode

Der erste Parameter fungiert als neuer Kontext "this". Zusätzlich können weitere Parameter übergeben werden diese werden an die Funktion weitergereicht. Sehr wichtig: Die bind() methode ruft die Funktion nicht auf, sondern erzeugt eine neue Funktion.

var context = {
 
    name: "Tom"
     
};
 
function bindMe(param1, param2)
{
     
    return param1 +' '+ this.name + param2;
     
}
 
var neueFunktion = bindMe.bind(context, "Hallo", "!");
 
console.log( neueFunktion() ); // Hallo Tom!

Apply und Call

Wer für Javascript guten Code schreiben will kommt an apply() und call() nicht vorbei. Apply, call und bind sind sich sehr ähnlich. Alle drei können den Kontext einer Funktion ändern. Die unterschiede zwischen den drei will ich kurz erklären:

Die call() Methode

Die call() Methode erwartet ein Kontext als Parameter und eine Liste an Parameter die der Funktion übergeben werden( genau wie bei bind() auch ). Anders als bei bind(), erzeugt call keine neue Funktion sondern ruft diese direkt auf.

var context = {
 
    name: "Tom"
     
};
 
function callMe(param1, param2)
{
     
    return param1 +' '+ this.name + param2;
     
}
 
callMe.call(context, "Hallo", "!"); // Hallo Tom!

Die apply() Methode

Die apply() Methode erwartet ebenfalls ein Kontext als parameter allerdings ist der zweite Parameter ein Array. Dieser Array wird der Funktion als Parameter übergeben. Sonst verhält sich apply wie die call Methode.

var context = {
 
    name: "Tom"
     
};
 
function applyMe(param1, param2)
{
    return param1 +' '+    + param2;
}
 
applyMe.apply(context, ["Hallo", "!"]); // Hallo Tom!
Zurück