Prototyper og arv i JavaScript

Prototyper og arv i JavaScript
Arv er et konsept fra objektorientert programmering, selv om JavaScript fullt ut støtter arv mellom foreldre og barn, er arbeidet langt fra den tradisjonelle objektorienterte programmeringen, det er fordi alt i JavaScript er kartlagt på den primitive konstruktøren Gjenstand (Objekt med kapital O) Det er grunnen til at det også er kjent som masterobjektet. Ikke tolke dette hovedobjektet med datatypeobjektet.

JavaScript blir ofte feiltolket som en Object-orientert språk, men i virkeligheten er det ikke sant; JavaScript er et prototypebasert språk. Arv i JavaScript oppnås av noe som heter Prototypisk arv. For å forstå det, må vi først være kjent med hvordan en konstruktør fungerer i JavaScript, hvordan et objekt opprettes mot en konstruktør, og hva som er prototypekjetting.

Dette er et av de avanserte temaene i JavaScript, og vi kommer til å ta deg veldig tregt og prøve å forklare hver eneste liten informasjon sammen med utdrag, la oss komme i gang.

Hvordan fungerer en konstruktør i JavaScript

Konvensjonelt, Konstruktører er spesielle funksjoner som utføres hver gang et objekt opprettes mot en klasse; I JavaScript, hvert funksjonsuttrykk er en Konstruktør. Hvis du kommer fra et trivielt programmeringsspråk og har litt bakgrunn med objektorientert programmering, vil du bli forvirret. Prøv derfor ikke å sammenligne JavaScript-konsepter med triviell objektorientert programmering.

Selv om det med ankomsten av ES 6 -versjonen av JavaScript nøkkelordet "Klasse”Ble lagt til i JavaScript, men det brukes ikke til å implementere arvekonseptet. I JavaScript kan du lage objekter som er kartlagt på funksjonen, ja - funksjoner.

Se for deg en funksjon opprettet med følgende kode:

var person = funksjon ()

Som nevnt ovenfor, at hvert funksjonsuttrykk er en konstruktør, kan dette bevises ved å bruke følgende linjer inne i funksjonen:

var person = funksjon (navn)
dette.Navn = navn;
dette.Alder = 20

Nå, som du ser, lager vi en funksjon og inne i funksjonens kropp, definerer vi og initialiserer egenskapene til objektet, akkurat som vi gjør i en normal konvensjonell konstruktør. La oss nå lage noen gjenstander som er kartlagt til dette Personens Konstruktørfunksjon med følgende kodelinjer:

var p1 = ny person ("John");
var p2 = ny person ("Albert");

Nå lager vi objekter, men vi har ingen metode i objekter som vil gi oss navnet på personen vi nettopp opprettet, så la oss lage den funksjonen inne i konstruktøren til Person gjenstand.

var person = funksjon (navn)
dette.Navn = navn;
dette.Alder = 20;
dette.getName = funksjon ()
Returner (dette.Navn)

Nå må vi kalle denne funksjonen fra hvert enkelt objekt ved å bruke følgende kodelinjer:

konsoll.Logg (P1.getName ());
konsoll.Logg (P2.getName ());

Etter å ha kjørt hele utdraget får vi følgende utgang på konsollen:

Nå er her det største problemet med å bruke denne typen mal, forestill deg at du har 100 objekter av Person, Disse 100 objektene vil ha sine egen 100 annerledes getName() Funksjoner:

Dette er fordi disse objektene er forekomstene av Person, dermed gjøre det overflødig på minnet. Det er her Prototypeegenskaper kommer i spill.

Prototypeegenskapen

Hver funksjon og hvert objekt har en egenskap som er navngitt Prototype, Denne prototypen inneholder metoder og egenskaper til en funksjon, og denne prototypeegenskapen deles mellom alle forekomster/objekter som er kartlagt til funksjonen, ta en titt på dette utdraget:

Hvis vi skulle lage noen objekter basert på denne funksjonen “x”, Ville de arve metodene og egenskapene i“prototype”Av funksjonen. I vårt eksempel ville hovedfunksjonen være Person Og gjenstandene er P1, P2, som:

Bruke prototypeegenskaper for å lage prototypisk arv

Vårt viktigste problem med den trivielle tilnærmingen var at hvert eneste objekt hadde sin egen getName() Funksjoner, jo mer gjenstandene desto mer er antallet av getName() Funksjoner i minnet. For å fjerne dette, skriver vi getName () -funksjon Utenfor konstruktøruttrykket og inne i prototypeegenskapen ved hjelp av syntaks:

ObjectName.prototype.MethodName

Koden vår endres til:

var person = funksjon (navn)
dette.Navn = navn;
dette.Alder = 20;

person.prototype.getName = funksjon ()
Returner dette.Navn;

var p1 = ny person ("John");
var p2 = ny person ("Albert");
konsoll.Logg (P1.getName ());
konsoll.Logg (P2.getName ());

Utgangen er nøyaktig den samme som forrige gang:

Men forskjellen denne gangen er at snarere enn at hvert objekt har sin egen getName() Funksjon, hvert objekt får tilgang til getName() Funksjon i foreldrene og bruke den funksjonen til å utføre instruksjonen gitt til den. Dette kalles "Prototypisk arv”I JavaScript. Etter hvert, ikke gjør det overflødig i minnet.

Masterobjekt

Alt i JavaScript er egentlig et objekt, dette betyr at alt i JavaScript er basert på Gjenstand (med en kapital o).

For å forklare dette, bruk følgende kodelinjer og åpne konsollen i nettleseren.

var demo = funksjon ()

konsoll.dir (demo);

Du lager en funksjon med en tom konstruktør og konsoll.dir() Viser detaljene om demo() Funksjonsdefinisjon på konsollen, du vil se dette:

Utvid den lille pilspissen, og undersøk __proto__ egenskap til denne funksjonen, __proto__ Eiendom forteller oss om hvilket objekt som ble kartlagt, vil du se dette:

La oss nå lage en forekomst av denne demo -funksjonen og undersøke den __proto__ som:

var demo = funksjon ()

La x = ny demo ();
konsoll.dir (x);

Etter å ha kjørt denne koden, bør du se følgende utdata på konsollen:

Utvid dette og undersøk konstruktøren som forekomsten “X” ble kartlagt, vil du se:

Som betyr det objektet x har foreldredemoen, og vi vet allerede at Funksjonsdemoer kartlagt på JavaScript -objektet. Dette skaper en prototypingkjede som:

Objektet "x”Kan få tilgang til metodene og egenskapene til hovedobjektet, og dermed skape en arvekjede.

Hvis vi ser i konsollen vår for siste gang, kan vi undersøke at hovedobjektet har denne ene metoden i sin prototypeegenskap som er toString () som:

Og vi kaller denne egenskapen på objektet “x”Og på funksjonen demo som du opprettet som:

konsoll.Logg (x.toString ());
konsoll.Logg (demo.toString ());

Du får utdataene som:

Du kan se, både objektet og funksjonen kunne få tilgang til denne metoden, selv om den ikke ble definert i dem.

Slik fungerer arv i JavaScript gjennom prototyper.

Konklusjon

Arv i JavaScript er veldig forskjellig fra vår konvensjonelle definisjon av arv i objektorientert programmering. I JavaScript oppnår vi arv ved hjelp av en eiendom som heter prototype. Du lærte hvordan en konstruktør fungerer i JavaScript, hva er prototype Eiendom, hvordan alt i JavaScript er et objekt ved å lære om Masterobjekt. Dessuten lærte du om prototypisk arv og prototypekjedering, og du kunne få tilgang til metodene og egenskapene til Masterobjekt bruker gjenstand som du opprettet.