Inleiding
JavaScript is een op prototype gebaseerde taal, en elk object in JavaScript heeft een verborgen interne eigenschap genaamd]
die kan worden gebruikt om objecteigenschappen en methoden uit te breiden. U kunt meer lezen over prototypes in onze Understanding Prototypes and Inheritance in JavaScript tutorial.
tot voor kort gebruikten ijverige ontwikkelaars constructorfuncties om een objectgeoriënteerd ontwerppatroon na te bootsen in JavaScript., De taalspecificatie ECMAScript 2015, vaak aangeduid als ES6, introduceerde klassen om de JavaScript-taal. Klassen in JavaScript bieden eigenlijk geen extra functionaliteit, en worden vaak beschreven als het verstrekken van “syntactische suiker” over prototypes en erfenis in die zin dat ze bieden een schonere en meer elegante syntaxis. Omdat andere programmeertalen gebruik maken van klassen, maakt de class syntaxis in JavaScript het eenvoudiger voor ontwikkelaars om te bewegen tussen talen.
klassen zijn functies
een JavaScript-klasse is een type functie., Klassen worden gedeclareerd met hetclass
sleutelwoord. We zullen de syntaxis van de functieuitdrukking gebruiken om een functie te initialiseren en de syntaxis van de klassenuitdrukking om een klasse te initialiseren.
// Initializing a function with a function expressionconst x = function() {}
// Initializing a class with a class expressionconst y = class {}
We kunnen de ]
van een object benaderen met behulp van de methode Object.getPrototypeOf()
. Laten we dat gebruiken om de lege functie te testen die we gemaakt hebben.
Object.getPrototypeOf(x);
Outputƒ () { }
We kunnen die methode ook gebruiken op de klasse die we zojuist hebben aangemaakt.,
Object.getPrototypeOf(y);
Outputƒ () { }
de code gedeclareerd met function
en class
beide retourneren een functie ]
. Met prototypes kan elke functie een constructor-instantie worden met behulp van het new
sleutelwoord.
Outputx {}constructor: ƒ ()
Dit geldt ook voor klassen.
Outputy {}constructor: class
deze voorbeelden van prototypes zijn verder leeg, maar we kunnen zien hoe onder de syntaxis beide methoden hetzelfde eindresultaat bereiken.,
Defining a Class
In de prototypes and inheritance tutorial hebben we een voorbeeld gemaakt gebaseerd op het maken van tekens in een tekst-gebaseerd rollenspel. Laten we hier verder gaan met dat voorbeeld om de syntaxis van functies naar klassen bij te werken.
een constructorfunctie wordt geïnitialiseerd met een aantal parameters, die worden toegewezen als eigenschappen van this
, verwijzend naar de functie zelf. De eerste letter van de identifier zou worden gekapitaliseerd door conventie.
// Initializing a constructor functionfunction Hero(name, level) { this.name = name; this.level = level;}
wanneer we dit vertalen naar de class syntaxis, hieronder weergegeven, zien we dat het zeer gelijkaardig gestructureerd is.
// Initializing a class definitionclass Hero { constructor(name, level) { this.name = name; this.level = level; }}
we weten dat een constructorfunctie bedoeld is als een object blauwdruk door de hoofdletter van de eerste letter van de initializer (die optioneel is) en door vertrouwdheid met de syntaxis. Hetclass
sleutelwoord communiceert op een meer eenvoudige manier het doel van onze functie.,
het enige verschil in de syntaxis van de initialisatie is het gebruik van het class
sleutelwoord in plaats van function
, en het toewijzen van de eigenschappen binnen een constructor()
methode.
Defining Methods
de gangbare praktijk met constructorfuncties is om methoden direct toe te wijzen aan de prototype
in plaats van in de initialisatie, zoals te zien in de greet()
methode hieronder.
met klassen deze syntaxis is vereenvoudigd, en de methode kan direct worden toegevoegd aan de klasse., Met behulp van de methode definitie steno geà ntroduceerd in ES6, het definiëren van een methode is een nog beknopter proces.
laten we eens kijken naar deze eigenschappen en methoden in actie. We zullen een nieuwe instantie van Hero
aanmaken met behulp van het new
sleutelwoord, en enkele waarden toewijzen.
const hero1 = new Hero('Varg', 1);
als we meer informatie over ons nieuwe object printen met console.log(hero1)
, kunnen we meer details zien over wat er gebeurt met de klasse-initialisatie.,
OutputHero {name: "Varg", level: 1}__proto__: ▶ constructor: class Hero ▶ greet: ƒ greet()
We kunnen in de uitvoer zien dat de constructor()
en greet()
functies werden toegepast op de __proto__
, of ]
van hero1
, en niet direct als methode op het hero1
object. Hoewel dit duidelijk is bij het maken van constructorfuncties, is het niet duidelijk tijdens het maken van klassen. Klassen zorgen voor een meer eenvoudige en beknopte syntaxis, maar offeren enige duidelijkheid in het proces.,
een klasse uitbreiden
een voordeel van constructorfuncties en klassen is dat ze kunnen worden uitgebreid tot nieuwe object blauwdrukken gebaseerd op de ouder. Dit voorkomt herhaling van code voor objecten die vergelijkbaar zijn, maar een aantal extra of meer specifieke functies nodig hebben.
Nieuwe constructorfuncties kunnen worden gemaakt van de ouder met behulp van de call()
methode., In het onderstaande voorbeeld zullen we een meer specifieke tekenklasse aanmaken, genaamd Mage
, en de eigenschappen van Hero
eraan toewijzen door gebruik te maken van call()
, evenals het toevoegen van een extra eigenschap.
Op dit punt kunnen we een nieuwe instantie van Mage
aanmaken met dezelfde eigenschappen als Hero
evenals een nieuwe die we hebben toegevoegd.,
const hero2 = new Mage('Lejon', 2, 'Magic Missile');
het verzenden van hero2
naar de console, we kunnen zien dat we een nieuwe Mage
hebben gemaakt op basis van de constructor.
OutputMage {name: "Lejon", level: 2, spell: "Magic Missile"}__proto__: ▶ constructor: ƒ Mage(name, level, spell)
bij ES6-klassen wordt het sleutelwoord super
gebruikt in plaats van call
om toegang te krijgen tot de bovenliggende functies. We zullen extends
gebruiken om naar de bovenliggende klasse te verwijzen.
nu kunnen we een nieuwe Mage
instantie maken op dezelfde manier.,
const hero2 = new Mage('Lejon', 2, 'Magic Missile');
we zullen hero2
naar de console afdrukken en de uitvoer bekijken.
OutputMage {name: "Lejon", level: 2, spell: "Magic Missile"}__proto__: Hero ▶ constructor: class Mage
De uitvoer is bijna precies hetzelfde, behalve dat in de klasse constructie de ]
is gekoppeld aan de ouder, in dit geval Hero
.
Hieronder is een zij-aan-zij vergelijking van het gehele proces van initialisatie, het toevoegen van methoden, en overerving van een constructorfunctie en een klasse.
hoewel de syntaxis heel anders is, is het onderliggende resultaat bijna hetzelfde tussen beide methoden. Klassen geven ons een meer beknopte manier van het maken van object blauwdrukken, en constructor functies beschrijven nauwkeuriger wat er gebeurt onder de motorkap.
conclusie
In deze tutorial leerden we over de overeenkomsten en verschillen tussen JavaScript constructor functies en ES6 klassen. Zowel klassen als constructeurs imiteren een object-georiënteerd overerving model naar JavaScript, dat is een prototype-gebaseerde overerving taal.,
het begrijpen van prototypische overerving is van het grootste belang om een effectieve JavaScript-ontwikkelaar te zijn. Bekend zijn met klassen is zeer nuttig, omdat populaire JavaScript-bibliotheken zoals React vaak gebruik maken van de syntaxis class
.