Sobes.tech
Junior

Objasnite kako funkcioniše nasledjivanje u JavaScript-u.

sobes.tech АИ

Одговор од АИ

Nasleđivanje u JavaScript-u realizuje se putem prototipa. Svaki objekat u JavaScript-u ima unutrašnju osobinu [[Prototype]] koja se odnosi na drugi objekat. Kada pokušavamo da pristupimo svojstvu ili metodi objekta koji nema direktno u sebi, JavaScript motor traži to svojstvo ili metodu u prototipu tog objekta. Ako ga ne pronađe, nastavlja pretragu kroz lanac prototipova koji se formira povezivanjem [[Prototype]], sve dok ne dostigne null (kraj lanca).

Postoje dva osnovna mehanizma nasleđivanja:

  1. Klasično prototipsko nasleđivanje (ES5 i ranije): Osnovano na korišćenju funkcija-konstruktora i njihovog svojstva prototype.

    // Funkcija-konstruktor
    function Životinja(ime) {
      this.ime = ime;
    }
    
    // Dodavanje metode u prototip
    Životinja.prototype.pričaj = function() {
      console.log(`${this.ime} pravi zvuk.`);
    };
    
    // Kreiranje instance
    const pas = new Životinja('Pas');
    
    // Pozivanje metode iz prototipa
    pas.pričaj(); // Izlaz: Pas pravi zvuk.
    
    // Prototip `dog` je `Životinja.prototype`
    console.log(Object.getPrototypeOf(pas) === Životinja.prototype); // true
    
  2. Klasično nasleđivanje (ES6 i kasnije): Koristi sintaksu class i extends, koja ispod haube i dalje koristi prototipe.

    // Osnovna klasa
    class Životinja {
      constructor(ime) {
        this.ime = ime;
      }
    
      pričaj() {
        console.log(`${this.ime} pravi zvuk.`);
      }
    }
    
    // Podklasa koja nasleđuje od Životinja
    class Pas extends Životinja {
      constructor(ime, vrste) {
        super(ime); // Pozivanje konstruktora roditeljske klase
        this.vrste = vrste;
      }
    
      laje() {
        console.log(`${this.ime} laje.`);
      }
    }
    
    // Kreiranje instance podklase
    const mojPas = new Pas('Bublik', ['Labrador', 'Collie']);
    
    // Pozivanje metoda iz obe klase
    mojPas.pričaj(); // Izlaz: Bublik pravi zvuk.
    mojPas.laje();  // Izlaz: Bublik laje.
    
    // Prototip `Pas.prototype` je `Životinja.prototype`
    console.log(Object.getPrototypeOf(mojPas) === Pas.prototype); // true
    
    // Prototip `Pas.prototype` je `Životinja.prototype`
    console.log(Object.getPrototypeOf(Pas.prototype) === Životinja.prototype); // true
    

Ključne koncepcije:

  • Lanac prototipa: Veza između objekata preko njihovog [[Prototype]].

  • __proto__ (zastarjelo/ne standardno, ali korisno za razumevanje): Svojstvo preko kojeg se može pristupiti [[Prototype]]. Nije preporučljivo koristiti u produkcijskom kodu.

  • Object.getPrototypeOf(obj): Standardni način za dobijanje prototipa objekta.

  • Object.setPrototypeOf(obj, proto): Standardni način za promenu prototipa objekta (nije preporučljivo menjati prototipove već postojećih objekata nakon njihove kreacije).

  • instanceof: Operator za proveru da li je objekat instanca klase ili konstrukcione funkcije, putem provere njegovog lanca prototipa.

    console.log(mojPas instanceof Pas);   // true
    console.log(mojPas instanceof Životinja); // true
    console.log(mojPas instanceof Object); // true (na kraju lanca je `Object.prototype`)
    
  • super: Koristi se u klasama za pozivanje metoda ili konstruktora roditeljske klase.

Razlika između klasičnog i klasičnog pristupa: Klase pružaju strukturiraniji i sintaktički udobniji način rada sa prototipskim nasleđivanjem, sličan drugim programskim jezicima. Međutim, osnovni mehanizam ostaje isti — nasleđivanje preko prototipa.