this in JavaScript ist berüchtigt — kein anderes Sprach-Detail führt zu so vielen Bug-Tickets. Die gute Nachricht: hinter dem Verhalten stehen vier klare Binding-Regeln, die je nach Aufruf-Form greifen. Default-Binding (freier Funktions-Aufruf), Implicit-Binding (Methoden-Aufruf), Explicit-Binding (call/apply/bind) und New-Binding (Konstruktor-Aufruf). Wer die Reihenfolge ihrer Anwendung kennt, kann this bei jeder Code-Stelle eindeutig bestimmen. Dazu kommt noch das lexical this der Arrow Functions, das gar keine eigenen Bindings hat — und der Unterschied zwischen strict und sloppy Mode für Default-Binding. Dieser Artikel erklärt alle Regeln mit Code und nennt die häufigsten Fallen.

Was ist this?

this ist ein implicit-übergebener Parameter jeder klassischen Funktion. Sein Wert hängt davon ab, wie die Funktion aufgerufen wird — nicht davon, wie oder wo sie definiert wurde.

JavaScript this-grundidee.js
function zeig() {
    console.log('this:', this);
}

// Freier Aufruf
zeig();                                  // this = undefined (strict) / globalThis (sloppy)

// Als Methode
const obj = { name: 'A', zeig };
obj.zeig();                              // this = obj

// Explicit
zeig.call({ name: 'B' });                // this = { name: 'B' }

// Als Konstruktor
new zeig();                              // this = neues leeres Object
Output
this: undefined
this: { name: 'A', zeig: [Function: zeig] }
this: { name: 'B' }
this: zeig {}

Dieselbe Funktion, vier verschiedene this-Werte — je nach Aufruf-Form.

Regel 1: Default-Binding (freier Aufruf)

Ein Funktions-Aufruf ohne Owner-Object und ohne Konstruktor liefert das Default-Binding. In Strict Mode: undefined. In Sloppy Mode: das globale Object (globalThis, window, global).

JavaScript default-binding.js
'use strict';

function f() {
    console.log('strict:', this);
}

f(); // undefined — Default in Strict Mode
Output
strict: undefined

In Sloppy Mode wäre this hier globalThis (in Browsern: window). ESM-Module sind automatisch im Strict Mode — daher ist Sloppy-Default heute selten Thema.

Regel 2: Implicit-Binding (Methoden-Aufruf)

Wenn eine Funktion über obj.methode() aufgerufen wird, ist this das Object links vom Punkt.

JavaScript implicit-binding.js
const user = {
    name: 'Anna',
    gruss() {
        console.log('Hallo,', this.name);
    },
};

user.gruss();   // this = user

const verschachtelt = {
    innen: user,
};
verschachtelt.innen.gruss();   // this = user (letzter Punkt zählt)
Output
Hallo, Anna
Hallo, Anna

Wichtig: nur das letzte Object vor dem Methoden-Aufruf zählt. Selbst bei tief verschachtelten Property-Zugriffen.

Implicit-Binding verlieren

Wer eine Methode aus dem Object entkoppelt — also nur die Funktion in einer Variable speichert oder als Callback weitergibt — verliert das Implicit-Binding.

JavaScript implicit-verlust.js
const user = {
    name: 'Anna',
    gruss() {
        console.log('Hallo,', this?.name);
    },
};

user.gruss();          // Hallo, Anna

const ref = user.gruss;
ref();                 // Hallo, undefined — Implicit weg, Default-Binding

setTimeout(user.gruss, 10);   // Hallo, undefined — Callback verliert this
Output
Hallo, Anna
Hallo, undefined
Hallo, undefined

Klassische Falle: man übergibt eine Methode als Callback, und der Aufrufer ruft sie ohne den Owner-Kontext auf. Lösung: user.gruss.bind(user) oder ein Arrow-Wrapper () => user.gruss().

Regel 3: Explicit-Binding (call, apply, bind)

Mit call, apply und bind kann man this explizit setzen. Details im eigenen Artikel — hier nur die Übersicht.

JavaScript explicit-binding.js
function gruss(salut) {
    console.log(`${salut}, ${this.name}!`);
}

const a = { name: 'Anna' };
const b = { name: 'Bob' };

gruss.call(a, 'Hi');     // call: this + Argumente einzeln
gruss.apply(b, ['Hey']); // apply: this + Argumente als Array

const grussFuerA = gruss.bind(a, 'Hallo');
grussFuerA();            // bind: liefert neue Funktion mit gebundenem this
Output
Hi, Anna!
Hey, Bob!
Hallo, Anna!

Explicit-Binding ist stärker als Implicit-Binding — wenn fn.call(x) aufgerufen wird, gewinnt x, egal woher die Funktion kommt.

Regel 4: New-Binding (Konstruktor)

Mit new fn() passiert vier Dinge: ein neues leeres Object wird erzeugt, das Object wird mit dem Prototyp der Funktion verknüpft, die Funktion wird mit this = neues Object aufgerufen, und (sofern die Funktion keinen Object zurückgibt) wird this automatisch returnt.

JavaScript new-binding.js
function Auto(marke) {
    this.marke = marke;
    this.geschwindigkeit = 0;
}

Auto.prototype.beschleunigen = function() {
    this.geschwindigkeit += 10;
};

const a = new Auto('VW');
a.beschleunigen();
a.beschleunigen();
console.log(a); // Auto { marke: 'VW', geschwindigkeit: 20 }
Output
Auto { marke: 'VW', geschwindigkeit: 20 }

Moderne Codebasen nutzen für Konstruktoren typischerweise class, das intern dieselbe Mechanik implementiert.

Reihenfolge der Bindings

Wenn mehrere Regeln greifen könnten, ist die Priorität:

  1. New-Binding (new fn()) — höchste Priorität
  2. Explicit-Binding (fn.call(obj), fn.apply(obj), fn.bind(obj)())
  3. Implicit-Binding (obj.fn())
  4. Default-Binding (fn()) — niedrigste Priorität
JavaScript prioritaeten.js
function f() { console.log(this?.name); }

const a = { name: 'A', f };
const b = { name: 'B' };

// 1: Implicit
a.f();                       // 'A'

// 2: Explicit > Implicit
a.f.call(b);                 // 'B'

// 3: bind > Implicit, Explicit
const fb = f.bind(b);
const c = { name: 'C', m: fb };
c.m();                       // 'B' — bind gewinnt
fb.call({ name: 'X' });      // 'B' — call kann bind nicht ändern

// 4: new > bind
function Constr() { this.name = 'Neues Object'; console.log(this.name); }
const NeuConst = Constr.bind(b);
new NeuConst();              // 'Neues Object' — new schlägt bind
Output
A
B
B
B
Neues Object

Arrow Functions: lexical this

Arrow Functions haben kein eigenes this. Sie übernehmen das this ihres umgebenden Scopes, lexikalisch bestimmt. Die vier Binding-Regeln gelten für sie nicht.

JavaScript arrow-this.js
const obj = {
    name: 'Anna',
    klassisch() {
        setTimeout(function() {
            console.log('classic:', this?.name);   // undefined
        }, 0);
    },
    arrow() {
        setTimeout(() => {
            console.log('arrow:  ', this?.name);   // 'Anna'
        }, 0);
    },
};

obj.klassisch();
obj.arrow();
Output
classic: undefined
arrow:   Anna

Das macht Arrows zur idealen Wahl für Inner-Callbacks in Methoden. call/apply/bind haben auf Arrows keinen Effektthis bleibt lexikalisch.

Strict vs. Sloppy Mode

Der einzige Unterschied: das Default-Binding — also this bei freiem Funktions-Aufruf.

  • Sloppy: this = globalThis (window im Browser, global in Node).
  • Strict: this = undefined.
JavaScript strict-vs-sloppy.js
// Sloppy
function sloppy() {
    return this;
}

function strict() {
    'use strict';
    return this;
}

console.log(typeof sloppy());   // 'object' (globalThis)
console.log(typeof strict());   // 'undefined'
Output
object
undefined

ESM-Module und class-Bodies sind automatisch Strict — daher ist Sloppy-Default-Binding in modernem Code selten Thema. Aber: in <script>-Tags ohne type="module" läuft Code per Default in Sloppy Mode.

Häufige Fallen — kompakte Übersicht

SituationSymptomLösung
Methode als Callback übergebenthis ist undefinedbind(obj) oder Arrow-Wrapper
setTimeout(obj.method, ...)this ist undefinedsetTimeout(() => obj.method(), ...)
Methode aus Object destrukturierenthis ist undefinednicht destrukturieren, oder bind
Arrow als Object-Methodethis ist nicht das ObjectMethoden-Shorthand statt Arrow
Arrow als Event-Handler im DOMthis ist nicht das Elementklassische Funktion oder e.currentTarget
this in verschachtelter Funktioninnere Funktion hat eigenes thisinnere als Arrow definieren
new weggelassenthis = globalThis in Sloppyclass (wirft TypeError) oder Strict Mode

Häufige Stolperfallen

Methode entkoppelt — this wird undefined

const ref = obj.method; ref(); verliert das Implicit-Binding. Häufig bei Callbacks: setTimeout(obj.method, ...), arr.forEach(obj.method), button.addEventListener('click', obj.method). Lösung: bind oder Arrow-Wrapper.

Arrow als Object-Methode — this zeigt nicht auf Object

const obj = { name: 'A', f: () => this.name } — die Arrow erbt this vom umgebenden Modul-Scope (in ESM: undefined, im Browser-Script: window). Lösung: Methoden-Shorthand { f() { ... } }.

setTimeout-Callback hat eigenes this — undefined in Strict

Ohne Bind oder Arrow ist this im setTimeout-Callback in Strict-Mode undefined. In Sloppy ist es globalThis. Empfehlung: immer Arrow-Function als Callback nutzen, dann erbt sie das umgebende this.

Verschachtelte klassische Funktionen verlieren this

Innerhalb einer Methode definiert man eine innere klassische Funktion — und in deren Body ist this nicht mehr das Owner-Object. Vor Arrow-Functions war const self = this der Standard-Hack. Heute: innere Funktion als Arrow definieren.

Class-Methode entkoppelt: TypeError statt undefined

Bei Class-Methoden ist der Body automatisch Strict. Wer eine entkoppelte Methode aufruft (const m = c.method; m();), bekommt einen TypeError beim ersten this.x-Zugriff — anders als bei Object-Methoden. Lösung: Arrow-Class-Field method = () => ... für auto-bind.

new bei Funktion ohne Schreibweisen-Konvention — bug-anfällig

Wer eine normale Funktion versehentlich mit new aufruft, bekommt ein leeres Object und potenziell unsinnige Properties. Schutz: class nutzen — Constructors ohne new werfen TypeError, vermeidbare Fehler werden laut. Bei traditionellen Constructors: if (!(this instanceof Foo))-Guard am Anfang.

bind erzeugt eine neue Funktion, Original bleibt

const bound = fn.bind(obj) liefert eine NEUE Funktion mit fixiertem this. fn selbst bleibt unverändert. Subtile Falle: man bindet zweimal — die zweite bind hat keinen Effekt mehr, weil bind-Funktionen bereits ein hardes this haben und nicht überschrieben werden.

Arrows ignorieren call/apply/bind

arrow.call(obj) ändert NICHT this der Arrow. Das macht Arrows angenehm-vorhersagbar — aber wer auf call-Mechanik angewiesen ist (z.B. Generic-Mixins), darf keine Arrow nehmen.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Funktionen

Zur Übersicht