Capire l’ereditarietà prototipale di JavaScript

Ereditarietà

L’ereditarietà è il processo con cui un oggetto può essere basato su un altro. Questo permette agli oggetti di condividere le proprietà dell’altro.

Ho creato il prototipo Hero e l’ho usato per creare un nuovo oggetto chiamato superman. Ma non stiamo facendo nulla con questo oggetto. Quindi occupiamoci di questo creando un’altra funzione chiamata dialogue.

function dialogue() {
console.log('I am ' + this.name);
}

Ma se ora eseguiamo il nostro codice, non succederà nulla perché questa funzione non sa qual è il nome reale. Per questo, abbiamo bisogno di

Voglio che questa nuova funzione abbia le stesse proprietà di quella Hero. Invece di scriverle all’interno di questa funzione, possiamo semplicemente dire a JavaScript di ereditarle dal prototipo Hero.

Questo è possibile con l’aiuto della proprietà prototype che è disponibile in qualsiasi oggetto in JavaScript.

Mettendo dialogue su Hero.prototype, lo abbiamo reso disponibile a tutte le istanze di Hero.

Eredità differenziale

JavaScript ha anche un altro modello di eredità chiamato “eredità differenziale”. In questo modello, i metodi non sono copiati dal genitore al figlio. Ma invece c’è un legame tra i figli e il loro oggetto genitore.

Qui, superman in realtà non ha un suo metodo chiamato dialogue(). Ma allora come funziona superman.dialogue()?

Quando il motore JavaScript incontra superman.dialogue() nel codice, cerca la proprietà chiamata dialogue dentro l’oggetto superman. Quando non ne trova una, cercherà nella catena dei prototipi il genitore Hero.prototype di superman. Lì troverà Hero.prototype.dialogue e lo chiamerà con un this che è legato a superman.

Object.create()

Possiamo rendere questo ancora più esclusivo creando una nuova classe per Superman che erediterà le proprietà del prototipo Hero. Possiamo farlo assegnando il prototipo di Superman al prototipo di Hero in questo modo:

function Superman() {}
Superman.prototype = Hero.prototype

Ma questo non fa altro che rendere uguali sia Superman che Hero. Quello di cui abbiamo veramente bisogno è un nuovo oggetto che sia basato sul prototipo Hero. Da ES5, JavaScript ha una funzione integrata chiamata Object.create(). Usiamola qui come mostrato qui sotto:

Superman.prototype = Object.create(Hero.prototype);

Questo creerà un nuovo oggetto vuoto che è basato sul prototipo Hero e lo assegnerà al prototipo Superman. Così tutte le proprietà che abbiamo nel prototipo Hero possono ora essere accessibili dal prototipo Superman. Quindi invece di chiamare new Hero, possiamo chiamare new Superman e tutto funzionerà ancora come dovrebbe.

Ma se guardate più da vicino l’output, noterete che c’è un undefined al suo interno. Questo perché attualmente il Hero è un costruttore solo per se stesso. Dobbiamo call le proprietà di Hero all’interno del Superman prototipo.

function Superman() {
Hero.call(this, 'Superman', 'Clark Kent', 'Krypton')
}

Creiamo un altro costruttore chiamato MarvelMovies come mostrato qui sotto:

function MarvelMovies(movieName, releaseYear) {
this.movieName = movieName;
this.releaseYear = releaseYear;
}

Quando una funzione è usata come costruttore, this si riferisce al nuovo oggetto che stiamo creando. Così in questo costruttore, ho preso movieName e releaseYear come argomenti e ho assegnato questi valori alle proprietà movieName e releaseYear della nostra nuova istanza MarvelMovies chiamata avengers.

var avengers = new MarvelMovies("avengers", 2012);

Creerò poi un nuovo metodo chiamato output per questo prototipo come mostrato qui sotto:

MarvelMovies.prototype.output = function() {
return "Movie: " + this.movieName + " Released in " + this.releaseYear;
}
console.log(avengers.output());

Eredità futura

Un aspetto davvero fantastico dell’ereditarietà è che JavaScript vi permette di modificare o espandere le caratteristiche di una classe anche dopo averla definita.

JavaScript cercherà il prototipo quando si cerca di accedere alle proprietà di un oggetto. Quindi, potete alterare le classi in fase di esecuzione!

Per illustrare questo, creiamo un array come mostrato qui sotto:

var numbers = ;
Array.prototype.shuffle = function() {
return this.sort(function() {
return Math.round( Math.random() * 2) - 1;
});
};
console.log(numbers.shuffle());

Qui, l’array numbers esisteva prima di quello Array.prototype.shuffle. Ma in JavaScript, le ricerche delle proprietà risalgono la catena dei prototipi. Questo è il motivo per cui l’array ha ancora accesso al nuovo metodo shuffle, poiché esiste sul Array.prototype quando stiamo effettivamente cercando di usarlo.

In termini semplici, abbiamo creato un array, poi siamo tornati indietro e abbiamo dato a tutti gli array l’accesso a un nuovo metodo.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.