Sobes.tech
Middle

Cos'è l'ereditarietà prototipica in JavaScript?

sobes.tech AI

Risposta dell'AI

In JavaScript, gli oggetti ereditano proprietà e metodi dai loro prototipi. Il prototipo di ogni oggetto è un altro oggetto, le cui proprietà e metodi sono accessibili attraverso la catena dei prototipi.

Quando si accede a una proprietà di un oggetto, JavaScript la cerca prima direttamente nell'oggetto stesso. Se la proprietà non viene trovata, la ricerca continua nel prototipo di quell'oggetto, poi nel prototipo del prototipo, e così via, fino a trovare la proprietà o raggiungere la fine della catena (null).

L'ereditarietà prototipica si differenzia dall'ereditarietà classica (come in Java o C++), dove gli oggetti vengono creati da classi che descrivono la loro struttura e comportamento. In JavaScript, le classi, introdotte in ES6, sono uno zucchero sintattico sopra l'ereditarietà prototipica.

Aspetti principali:

  • __proto__: Proprietà interna dell'oggetto che fa riferimento al suo prototipo.
  • prototype: Proprietà del costruttore (funzione usata come costruttore), che fa riferimento all'oggetto che fungerà da prototipo per le istanze create.
  • Object.getPrototypeOf(obj): Metodo standard per ottenere il prototipo di un oggetto.
  • Object.setPrototypeOf(obj, proto): Metodo standard per impostare il prototipo di un oggetto.

Esempio:

// Funzione costruttrice
function Animal(name) {
  this.name = name;
}

// Aggiungi metodo al prototipo Animal
Animal.prototype.sayHello = function() {
  console.log(`Ciao, il mio nome è ${this.name}`);
};

// Crea un'istanza
const dog = new Animal("Buddy");

// Chiama metodo dal prototipo
dog.sayHello(); // Output: Ciao, il mio nome è Buddy

// Il prototipo di dog è Animal.prototype
console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true

// Il prototipo di Animal.prototype è Object.prototype
console.log(Object.getPrototypeOf(Animal.prototype) === Object.prototype); // true

// La fine della catena dei prototipi è null
console.log(Object.getPrototypeOf(Object.prototype) === null); // true

Confronto con l'ereditarietà classica (usando classi ES6):

class Animal {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log(`Ciao, il mio nome è ${this.name}`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // Chiamata al costruttore della classe genitore
    this.breed = breed;
  }

  bark() {
    console.log("Woof!");
  }
}

const buddy = new Dog("Buddy", "Golden Retriever");
buddy.sayHello(); // Output: Ciao, il mio nome è Buddy (eredita da Animal)
buddy.bark(); // Output: Woof! (metodo di Dog)

// Le classi in ES6 sono zucchero sintattico sopra i prototipi
console.log(Object.getPrototypeOf(Dog) === Animal); // true (ereditarietà di classi)
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true (ereditarietà di metodi tramite prototipi)
console.log(Object.getPrototypeOf(buddy) === Dog.prototype); // true (l'istanza eredita dal prototipo della classe)

L'ereditarietà prototipica è un concetto chiave in JavaScript, la cui comprensione è essenziale per lavorare efficacemente con il linguaggio.