Sobes.tech
Junior

Explica cum funcționează moștenirea în JavaScript.

sobes.tech AI

Răspuns de la AI

Moștenirea în JavaScript se realizează prin prototipuri. Fiecare obiect în JavaScript are o proprietate internă [[Prototype]] care face referire la un alt obiect. Când încercăm să accesăm o proprietate sau metodă a unui obiect care nu este prezentă direct pe acesta, motorul JavaScript caută această proprietate sau metodă în prototipul obiectului. Dacă nu o găsește acolo, continuă căutarea pe lanțul de prototipuri, format prin legăturile [[Prototype]], până când ajunge la null (sfârșitul lanțului).

Există două mecanisme principale de moștenire:

  1. Moștenirea prototipică clasică (ES5 și anterior): Bazată pe utilizarea funcțiilor constructor și a proprietății lor prototype.

    // Funcție constructor
    function Animal(name) {
      this.name = name;
    }
    
    // Adăugarea metodei în prototip
    Animal.prototype.speak = function() {
      console.log(`${this.name} emite un sunet.`);
    };
    
    // Crearea unei instanțe
    const dog = new Animal('Câine');
    
    // Apelarea metodei din prototip
    dog.speak(); // Va afișa: Câine emite un sunet.
    
    // Prototipul lui cat este Animal.prototype
    console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true
    
  2. Moștenirea bazată pe clase (ES6 și ulterior): Utilizează sintaxa class și extends, care operează intern tot cu prototipuri.

    // Clasa de bază
    class Animal {
      constructor(name) {
        this.name = name;
      }
    
      speak() {
        console.log(`${this.name} emite un sunet.`);
      }
    }
    
    // Subclasă care moștenește de la Animal
    class Dog extends Animal {
      constructor(name, breeds) {
        super(name); // Apelul constructorului clasei părinte
        this.breeds = breeds;
      }
    
      bark() {
        console.log(`${this.name} latră.`);
      }
    }
    
    // Crearea unei instanțe a subclasei
    const myDog = new Dog('Bublik', ['Labrador', 'Collie']);
    
    // Apelarea metodelor din Animal și Dog
    myDog.speak(); // Va afișa: Bublik emite un sunet.
    myDog.bark();  // Va afișa: Bublik latră.
    
    // Prototipul lui myDog este Dog.prototype
    console.log(Object.getPrototypeOf(myDog) === Dog.prototype); // true
    
    // Prototipul lui Dog.prototype este Animal.prototype
    console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
    

Concepte cheie:

  • Lanțul de prototipuri: Legătura între obiecte prin [[Prototype]].

  • __proto__ (învechit/nestandard, dar util pentru înțelegere): Proprietate prin care se poate accesa [[Prototype]]. Nu se recomandă utilizarea în producție.

  • Object.getPrototypeOf(obj) : Mod standard de a obține prototipul unui obiect.

  • Object.setPrototypeOf(obj, proto) : Mod standard de a modifica prototipul unui obiect (nu se recomandă modificarea prototipului obiectelor existente după crearea lor).

  • instanceof : Operator pentru verificarea dacă un obiect este instanța unei clase sau funcții constructor, verificând lanțul său de prototipuri.

    console.log(myDog instanceof Dog);   // true
    console.log(myDog instanceof Animal); // true
    console.log(myDog instanceof Object); // true (la sfârșitul lanțului Object.prototype)
    
  • super : Folosit în clase pentru a apela metodele sau constructorul clasei părinte.

Diferența între abordarea clasică și cea bazată pe clase: Clasele oferă o modalitate mai structurată și sintactic mai comodă de a lucra cu moștenirea prototipică, similar cu alte limbaje de programare. Cu toate acestea, mecanismul fundamental rămâne același — moștenirea prin prototipuri.