Kodokon kodokon.com

this, Prototypen und Klassen

Verstehe, wie this dynamisch aufgelöst wird, wie die Prototypenkette funktioniert und was Klassen dem Objektmodell wirklich hinzufügen.

10 Min. · 3 Fragen

Diese Lektion in Kodokon öffnen

Der Wert von this wird an der Aufrufstelle entschieden, nicht bei der Deklaration. Vier Regeln, in absteigender Priorität: der Aufruf mit new, die explizite Bindung (call, apply, bind), der Aufruf als Methode (obj.fn()) und ein einfacher Aufruf (fn()), der im Strict Mode undefined ergibt. Der häufigste Bug aus der Praxis folgt direkt daraus: Das Herauslösen einer Methode aus ihrem Objekt bricht die implizite Bindung.

JAVASCRIPT
const user = {
  name: "Ada",
  greet() {
    return "Hello, " + this.name;
  },
};
console.log(user.greet()); // "Hello, Ada"
const detached = user.greet;
// detached(); // TypeError: this is undefined
const bound = user.greet.bind(user);
console.log(bound()); // "Hello, Ada"
Die implizite Bindung verschwindet, sobald die Methode herausgelöst wird.

Arrow-Funktionen haben kein eigenes this: Sie fangen es lexikalisch aus dem umgebenden Gültigkeitsbereich ein, genau wie eine Closure. Das macht sie ideal für Callbacks, aber kontraproduktiv als Methoden an Objektliteralen, wo this auf den äußeren Gültigkeitsbereich zeigt. Unter der Haube delegiert jedes Objekt über seine Prototypenkette: Eine fehlende Eigenschaft wird Glied für Glied gesucht, bis null erreicht ist.

JAVASCRIPT
function Animal(name) {
  this.name = name;
}
Animal.prototype.describe = function () {
  return this.name + " is an animal";
};
const dog = new Animal("Rex");
console.log(dog.describe()); // "Rex is an animal"
console.log(Object.getPrototypeOf(dog) ===
  Animal.prototype); // true
console.log(dog.hasOwnProperty("describe")); // false
describe lebt auf dem Prototyp, geteilt von jeder Instanz.

Die class-Syntax ändert dieses Modell nicht: Sie macht es lesbar. Methoden, die im Klassenkörper deklariert werden, landen auf Constructor.prototype und werden daher geteilt. Instanzfelder (einschließlich Arrow-Funktionen, die als Felder zugewiesen werden) werden pro Instanz neu erzeugt: garantierte this-Bindung, aber vervielfachte Speicherkosten. Schließlich bieten #private-Felder eine von der Engine erzwungene Privatsphäre, anders als die _underscore-Konvention.

JAVASCRIPT
class BankAccount {
  #balance = 0;
  deposit(amount) {
    if (amount <= 0) throw new Error("Invalid amount");
    this.#balance += amount;
    return this;
  }
  get balance() {
    return this.#balance;
  }
}
const account = new BankAccount();
account.deposit(50).deposit(25);
console.log(account.balance); // 75
Von der Engine erzwungenes privates Feld und eine verkettbare API.

Wissenscheck

Stelle sicher, dass du die wichtigsten Punkte dieser Lektion behalten hast.

  1. Was ist this im Strict Mode bei einem einfachen Aufruf fn() ohne Objekt und ohne explizite Bindung?
    • globalThis
    • undefined
    • Das Objekt, in dem fn deklariert wurde
    • null
  2. Wo werden die im Klassenkörper deklarierten Methoden (ohne Felder) gespeichert?
    • Auf jeder Instanz, bei der Konstruktion kopiert
    • Auf Constructor.prototype, geteilt von allen Instanzen
    • In einem unzugänglichen internen Gültigkeitsbereich
  3. Was ist an einer Arrow-Funktion in Bezug auf this besonders?
    • Sie bindet this an das aufrufende Objekt, wie eine Methode
    • Sie hat kein eigenes this und fängt das aus dem umgebenden Gültigkeitsbereich ein
    • Sie bindet this immer an globalThis
    • Sie verbietet jeden Zugriff auf this