Förstå JavaScript:s prototypiska arv

Arv

Arv är den process genom vilken ett objekt kan baseras på ett annat. Detta gör att objekten kan dela varandras egenskaper.

Jag har skapat prototypen Hero och använt den för att skapa ett nytt objekt som heter superman. Men vi gör ingenting med detta objekt. Så låt oss ta hand om det genom att skapa en annan funktion som heter dialogue.

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

Men om vi kör vår kod nu kommer ingenting att hända eftersom den här funktionen inte vet vad namnet egentligen är. För detta måste vi

Jag vill att denna nya funktion ska ha samma egenskaper som Hero. Istället för att skriva ner dem inne i den här funktionen kan vi helt enkelt be JavaScript att ärva dem från Hero-prototypen.

Detta är möjligt med hjälp av prototype-egenskapen som är tillgänglig inom alla objekt i JavaScript.

Då vi placerar dialogueHero.prototype har vi gjort den tillgänglig för alla instanser av Hero.

Differentiell arv

JavaScript har också en annan arvsmodell som kallas ”differentiell arv”. I denna modell kopieras inte metoderna från föräldern till barnet. Utan istället finns det en länk mellan barnen och deras föräldraobjekt.

Här har superman faktiskt inte en egen metod som heter dialogue(). Men hur fungerar då superman.dialogue()?

När JavaScript-motorn stöter på superman.dialogue() i koden letar den efter egenskapen dialogue i superman-objektet. När den inte hittar en sådan letar den uppåt i prototypkedjan till supermans överordnade Hero.prototype. Där hittar den Hero.prototype.dialogue och anropar den med en this som är bunden till superman.

Object.create()

Vi kan göra detta ännu mer exklusivt genom att skapa en ny klass för Superman som kommer att ärva egenskaperna i Heros prototyp. Vi kan göra detta genom att tilldela Supermans prototyp till Heros prototyp så här:

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

Men vad detta gör är att det bara gör både och Hero lika. Vad vi egentligen behöver är ett nytt objekt som är baserat på prototypen Hero. Sedan ES5 har JavaScript en inbyggd funktion som heter Object.create(). Låt oss använda den här som visas nedan:

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

Detta kommer att skapa ett nytt tomt objekt som är baserat på prototypen Hero och tilldela det till prototypen Superman. Så alla egenskaper som vi har i Hero-prototypen kan nu nås av Superman-prototypen. Så istället för att ringa new Hero kan vi ringa new Superman och allt kommer fortfarande att fungera som det ska.

Men om du tittar närmare på resultatet kommer du att märka att det finns en undefined inuti det. Det beror på att Hero för närvarande bara är en konstruktör för sig själv. Vi måste call egenskaperna hos Hero inuti Superman prototypen.

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

Låt oss skapa en annan konstruktör som heter MarvelMovies som visas nedan:

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

När en funktion används som konstruktör hänvisar this till det nya objektet som vi skapar. I den här konstruktören har jag alltså tagit movieName och releaseYear som argument och tilldelat dessa värden till egenskaperna movieName och releaseYear för vår nya MarvelMovies instans som heter avengers.

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

Jag kommer sedan att skapa en ny metod som heter output för denna prototyp som visas nedan:

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

Framtida arv

En riktigt bra aspekt av arv är att JavaScript låter dig ändra eller utöka funktionerna i en klass även efter att du har definierat den.

JavaScript kommer att slå upp prototypen när du försöker få tillgång till egenskaperna på ett objekt. Du kan alltså ändra klasser vid körning!

För att illustrera detta kan vi skapa en array enligt nedan:

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

Här fanns arrayen numbers redan innan arrayen Array.prototype.shuffle fanns. Men i JavaScript går egenskapsökningarna uppåt i prototypkedjan. Därför får arrayen fortfarande tillgång till den nya metoden shuffle, eftersom den finns på Array.prototype när vi faktiskt försöker använda den.

Enklare uttryckt skapade vi en array, gick sedan tillbaka och gav alla Arrays tillgång till en ny metod.

Lämna ett svar

Din e-postadress kommer inte publiceras.