Sobes.tech
Junior

Erklären Sie, wie Vererbung in JavaScript funktioniert.

sobes.tech KI

Antwort von AI

Die Vererbung in JavaScript wird über Prototypen realisiert. Jedes Objekt in JavaScript hat eine interne Eigenschaft [[Prototype]], die auf ein anderes Objekt verweist. Wenn wir versuchen, auf eine Eigenschaft oder Methode eines Objekts zuzugreifen, die nicht direkt bei ihm vorhanden ist, sucht die JavaScript-Engine diese Eigenschaft oder Methode im Prototyp dieses Objekts. Wenn sie dort nicht gefunden wird, setzt die Suche in der Prototypkette fort, die durch die Verbindungen [[Prototype]] gebildet wird, bis sie null erreicht (Ende der Kette).

Es gibt zwei Hauptmechanismen der Vererbung:

  1. Klassische Prototypenvererbung (ES5 und früher): Basierend auf der Verwendung von Konstruktorfunktionen und deren Eigenschaft prototype.

    // Konstruktorfunktion
    function Animal(name) {
      this.name = name;
    }
    
    // Methode zum Prototyp hinzufügen
    Animal.prototype.speak = function() {
      console.log(`${this.name} gibt einen Ton von sich.`);
    };
    
    // Instanz erstellen
    const dog = new Animal('Hund');
    
    // Methode aus dem Prototyp aufrufen
    dog.speak(); // Gibt aus: Hund gibt einen Ton von sich.
    
    // Der Prototyp von cat ist Animal.prototype
    console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true
    
  2. Klassische Vererbung (ES6 und später): Nutzt die Syntax class und extends, die intern immer noch mit Prototypen arbeitet.

    // Basisklasse
    class Animal {
      constructor(name) {
        this.name = name;
      }
    
      speak() {
        console.log(`${this.name} gibt einen Ton von sich.`);
      }
    }
    
    // Unterklasse, die von Animal erbt
    class Dog extends Animal {
      constructor(name, breeds) {
        super(name); // Aufruf des Konstruktors der Elternklasse
        this.breeds = breeds;
      }
    
      bark() {
        console.log(`${this.name} bellt.`);
      }
    }
    
    // Instanz der Unterklasse erstellen
    const myDog = new Dog('Bublik', ['Labrador', 'Collie']);
    
    // Methoden von Animal und Dog aufrufen
    myDog.speak(); // Gibt aus: Bublik gibt einen Ton von sich.
    myDog.bark();  // Gibt aus: Bublik bellt.
    
    // Der Prototyp von myDog ist Dog.prototype
    console.log(Object.getPrototypeOf(myDog) === Dog.prototype); // true
    
    // Der Prototyp von Dog.prototype ist Animal.prototype
    console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
    

Wichtige Konzepte:

  • Prototypkette: Verbindung zwischen Objekten über ihre [[Prototype]].

  • __proto__ (veraltet/nicht standardisiert, aber nützlich zum Verstehen): Eigenschaft, über die auf [[Prototype]] zugegriffen werden kann. Wird in der Produktion nicht empfohlen.

  • Object.getPrototypeOf(obj) : Standardmethode, um den Prototyp eines Objekts zu erhalten.

  • Object.setPrototypeOf(obj, proto) : Standardmethode, um den Prototyp eines Objekts zu ändern (nicht empfohlen, den Prototyp nach der Erstellung zu ändern).

  • instanceof : Operator, um zu prüfen, ob ein Objekt eine Instanz einer Klasse oder Konstruktorfunktion ist, durch Überprüfung seiner Prototypkette.

    console.log(myDog instanceof Dog);   // true
    console.log(myDog instanceof Animal); // true
    console.log(myDog instanceof Object); // true (am Ende der Kette Object.prototype)
    
  • super : Wird in Klassen verwendet, um Methoden oder den Konstruktor der Elternklasse aufzurufen.

Der Unterschied zwischen klassischer und klassenbasierter Herangehensweise: Klassen bieten eine strukturiertere und syntaktisch bequemere Art, mit prototypischer Vererbung zu arbeiten, ähnlich wie in anderen Programmiersprachen. Das grundlegende Mechanismus bleibt jedoch derselbe — Vererbung durch Prototypen.