Sobes.tech
Junior

Leg uit hoe erfelijkheid werkt in JavaScript.

sobes.tech AI

Antwoord van AI

Erfelijkheid in JavaScript wordt geïmplementeerd via prototypes. Elk object in JavaScript heeft een interne eigenschap [[Prototype]] die verwijst naar een ander object. Wanneer we proberen toegang te krijgen tot een eigenschap of methode van een object die niet direct op dat object aanwezig is, zoekt de JavaScript-engine deze eigenschap of methode in het prototype van dat object. Als het niet wordt gevonden, gaat de zoektocht verder langs de prototypeketen die wordt gevormd door de verbindingen [[Prototype]], totdat null wordt bereikt (het einde van de keten).

Er zijn twee hoofdmechanismen van erfelijkheid:

  1. Klassieke prototype-erfenis (ES5 en eerder): Gebaseerd op het gebruik van constructorfuncties en hun eigenschap prototype.

    // Constructorfunctie
    function Animal(name) {
      this.name = name;
    }
    
    // Voeg methode toe aan prototype
    Animal.prototype.speak = function() {
      console.log(`${this.name} geeft een geluid.`);
    };
    
    // Maak een instantie
    const dog = new Animal('Hond');
    
    // Roep methode uit prototype aan
    dog.speak(); // Output: Hond geeft een geluid.
    
    // Het prototype van cat is Animal.prototype
    console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true
    
  2. Klassengebaseerde erfelijkheid (ES6 en later): Gebruikt de syntax class en extends, die intern nog steeds met prototypes werkt.

    // Basisklasse
    class Animal {
      constructor(name) {
        this.name = name;
      }
    
      speak() {
        console.log(`${this.name} geeft een geluid.`);
      }
    }
    
    // Subklasse die erft van Animal
    class Dog extends Animal {
      constructor(name, breeds) {
        super(name); // Aanroep van de constructor van de ouderklasse
        this.breeds = breeds;
      }
    
      bark() {
        console.log(`${this.name} blaft.`);
      }
    }
    
    // Maak een instantie van de subklasse
    const myDog = new Dog('Bublik', ['Labrador', 'Collie']);
    
    // Roep methoden aan van zowel Animal als Dog
    myDog.speak(); // Output: Bublik geeft een geluid.
    myDog.bark();  // Output: Bublik blaft.
    
    // Het prototype van myDog is Dog.prototype
    console.log(Object.getPrototypeOf(myDog) === Dog.prototype); // true
    
    // Het prototype van Dog.prototype is Animal.prototype
    console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
    

Belangrijke concepten:

  • Prototypeketen: Verbinding tussen objecten via hun [[Prototype]].

  • __proto__ (verouderd/niet-standaard, maar nuttig voor begrip): Eigenschap waarmee toegang tot [[Prototype]] mogelijk is. Niet aanbevolen voor gebruik in productie.

  • Object.getPrototypeOf(obj) : Standaardmethode om het prototype van een object te verkrijgen.

  • Object.setPrototypeOf(obj, proto) : Standaardmethode om het prototype van een object te wijzigen (niet aanbevolen om het prototype van bestaande objecten na creatie te wijzigen).

  • instanceof : Operator om te controleren of een object een instantie is van een klasse of constructorfunctie, door de prototypeketen te controleren.

    console.log(myDog instanceof Dog);   // true
    console.log(myDog instanceof Animal); // true
    console.log(myDog instanceof Object); // true (aan het einde van de keten Object.prototype)
    
  • super : Wordt gebruikt in klassen om methoden of de constructor van de ouderklasse aan te roepen.

Het verschil tussen de klassieke en de op klassen gebaseerde aanpak: Klassen bieden een meer gestructureerde en syntactisch comfortabele manier om met prototype-erfenis te werken, vergelijkbaar met andere programmeertalen. Het fundamentele mechanisme blijft echter hetzelfde — erfelijkheid via prototypes.