JavaScript är inte ett klassbaserat objektorienterat språk. Men det har fortfarande sätt att använda objektorienterad programmering (OOP).
i den här handledningen förklarar jag OOP och visar hur du använder den.
enligt Wikipedia är klassbaserad programmering
en stil av objektorienterad programmering (OOP) där arv sker via definierande klasser av objekt, istället för arv som sker via objekten ensamma
den mest populära modellen för OOP är klassbaserad.
men som jag nämnde är JavaScript inte en klassad baserad langauge-det är en prototypbaserad langauge.
enligt Mozillas documentaion:
ett prototypbaserat språk har begreppet ett prototypiskt objekt, ett objekt som används som en mall för att få de ursprungliga egenskaperna för ett nytt objekt.
ta en titt på den här koden:
let names = { fname: "Dillion", lname: "Megida"}console.log(names.fname);console.log(names.hasOwnProperty("mname"));// Expected Output// Dillion// false
Objektvariabeln names
har bara två egenskaper – fname
och lname
. Inga metoder alls.
så var kommer hasOwnProperty
från?
Tja, det kommer frånObject
prototyp.
försök logga innehållet i variabeln till konsolen:
console.log(names);
När du utökar resultaten i konsolen får du det här:
Lägg märke till den sista egenskapen – __proto__
? Försök att expandera det:
du ser en uppsättning egenskaper under Object
konstruktör. Alla dessa egenskaper kommer från den globala Object
prototypen. Om du tittar noga märker du också vårt dolda hasOwnProperty
.
med andra ord har alla objekt tillgång till Object
’s prototyp. De har inte dessa egenskaper, men får tillgång till egenskaperna i prototypen.
egenskapen __proto__
detta pekar på objektet som används som prototyp.
det här är egenskapen på varje objekt som ger den åtkomst till egenskapen Object prototype
.
varje objekt har den här egenskapen som standard, som hänvisar till Object Protoype
förutom när den är konfigurerad på annat sätt (det vill säga när objektets __proto__
pekas på en annan prototyp).
ändra egenskapen__ proto _ _
den här egenskapen kan ändras genom att uttryckligen ange att den ska hänvisa till en annan prototyp. Följande metoder används för att uppnå detta:
objekt.skapa ()
function DogObject(name, age) { let dog = Object.create(constructorObject); dog.name = name; dog.age = age; return dog;}let constructorObject = { speak: function(){ return "I am a dog" }}let bingo = DogObject("Bingo", 54);console.log(bingo);
i konsolen är det här vad du skulle ha:
Lägg märke till__proto__
egenskapen ochspeak
metoden?
Object.create
använder argumentet som skickas till det för att bli prototypen.
nytt nyckelord
function DogObject(name, age) { this.name = name; this.age = age;}DogObject.prototype.speak = function() { return "I am a dog";}let john = new DogObject("John", 45);
john
’s__proto__
egenskapen är riktad tillDogObject
’s prototyp. Men kom ihåg, DogObject
’s prototyp är ett objekt (nyckel-och värdepar), därför har den också en __proto__
egenskap som hänvisar till den globala Object
protoype.
denna teknik kallas PROTOTYPKEDJA.
Observera att:new
sökordsmetoden gör samma sak somObject.create()
men gör det bara lättare eftersom det gör vissa saker automatiskt för dig.
och så…
varje objekt i Javascript har tillgång tillObject
’s prototyp som standard. Om konfigurerad för att använda en annan prototyp, säg prototype2
, då prototype2
skulle också ha tillgång till objektets prototyp som standard, och så vidare.
Object + Function Combination
du är förmodligen förvirrad av det faktum att DogObject
är en funktion (function DogObject(){}
) och den har egenskaper som nås med en punktnotation. Detta kallas en funktionsobjektkombination.
När funktioner deklareras får de som standard många egenskaper som är kopplade till den. Kom ihåg att funktioner också är objekt i JavaScript-datatyper.
nu, klass
JavaScript introduceradeclass
nyckelordet i ECMAScript 2015. Det gör att JavaScript verkar som ett OOP-språk. Men det är bara synatiskt socker över den befintliga prototyptekniken. Den fortsätter sin prototypning i bakgrunden men får den yttre kroppen att se ut som OOP. Vi ska nu titta på hur det är möjligt.
följande exempel är en allmän användning av ett class
I JavaScript:
class Animals { constructor(name, specie) { this.name = name; this.specie = specie; } sing() { return `${this.name} can sing`; } dance() { return `${this.name} can dance`; }}let bingo = new Animals("Bingo", "Hairy");console.log(bingo);
detta är resultatet i konsolen:
__proto__
refererar tillAnimals
prototyp (som i sin tur refererar tillObject
prototyp).
från detta kan vi se att konstruktören definierar de viktigaste funktionerna medan allt utanför konstruktören (sing()
och dance()
) är bonusfunktionerna (prototyper).
i bakgrunden, med hjälp av sökordsmetoden new
översätts ovanstående till:
function Animals(name, specie) { this.name = name; this.specie = specie;}Animals.prototype.sing = function(){ return `${this.name} can sing`;}Animals.prototype.dance = function() { return `${this.name} can dance`;}let Bingo = new Animals("Bingo", "Hairy");
Subclassing
detta är en funktion i OOP där en klass ärver funktioner från en överordnad klass men har extra funktioner som föräldern inte gör.
tanken här är till exempel, säg att du vill skapa en kattklass. I stället för att skapa klassen från början – ange namn, ålder och artfastighet på nytt, skulle du ärva dessa egenskaper från föräldradjursklassen.
denna kattklass kan då ha extra egenskaper som whiskers färg.
Låt oss se hur underklasser görs med class
.
Här behöver vi en förälder som underklassen ärver från. Undersök följande kod:
class Animals { constructor(name, age) { this.name = name; this.age = age; } sing() { return `${this.name} can sing`; } dance() { return `${this.name} can dance`; }} class Cats extends Animals { constructor(name, age, whiskerColor) { super(name, age); this.whiskerColor = whiskerColor; } whiskers() { return `I have ${this.whiskerColor} whiskers`; }}let clara = new Cats("Clara", 33, "indigo");
med ovanstående får vi följande utgångar:
console.log(clara.sing());console.log(clara.whiskers());// Expected Output// "Clara can sing"// "I have indigo whiskers"
När du loggar innehållet i clara ut i konsolen har vi:
Du kommer att märka att clara
har en __proto__
egenskap som refererar till konstruktören Cats
och får tillgång till whiskers()
metod. Denna __proto__
egenskapen har också en __proto__
egenskap som refererar till konstruktören Animals
därigenom få tillgång till sing()
och dance()
name
och age
är egenskaper som finns på varje objekt som skapas från detta.
med metodenObject.create
översätts ovanstående till:
function Animals(name, age) { let newAnimal = Object.create(animalConstructor); newAnimal.name = name; newAnimal.age = age; return newAnimal;}let animalConstructor = { sing: function() { return `${this.name} can sing`; }, dance: function() { return `${this.name} can dance`; }}function Cats(name, age, whiskerColor) { let newCat = Animals(name, age); Object.setPrototypeOf(newCat, catConstructor); newCat.whiskerColor = whiskerColor; return newCat;}let catConstructor = { whiskers() { return `I have ${this.whiskerColor} whiskers`; }}Object.setPrototypeOf(catConstructor, animalConstructor);const clara = Cats("Clara", 33, "purple");clara.sing();clara.whiskers();// Expected Output// "Clara can sing"// "I have purple whiskers"
Object.setPrototypeOf
är en metod som tar in två argument – objektet (första argumentet) och den önskade prototypen (andra argumentet).
från ovanstående returnerar funktionen Animals
ett objekt med animalConstructor
som prototyp. FunktionenCats
returnerar ett objekt medcatConstructor
som prototyp. catConstructor
å andra sidan ges en prototyp av animalConstructor
.
därför har vanliga djur endast tillgång till animalConstructor
men katter har tillgång till catConstructor
och animalConstructor
.
inslagning upp
JavaScript utnyttjar sin prototyp natur att välkomna OOP utvecklare till sitt ekosystem. Det ger också enkla sätt att skapa prototyper och organisera relaterade data.
sanna OOP-språk utför inte prototyper i bakgrunden – bara notera det.
ett stort tack till Will sentances kurs på Frontend Masters-JavaScript: de hårda delarna av objektorienterad JavaScript. Jag lärde mig allt du ser i den här artikeln (plus lite extra forskning) från hans kurs. Du borde kolla in det.
Du kan slå mig på Twitter på iamdillion för frågor eller bidrag.
Tack för att du läste 🙂