JavaScript maakt gebruik van prototypal inheritance: elk object erft eigenschappen en methoden van zijn prototype object.
De traditionele klasse als blauwdruk om objecten te maken, gebruikt in talen als Java of Swift, bestaat niet in JavaScript. De prototypale overerving behandelt alleen objecten.
De prototypale overerving kan de klassieke overerving nabootsen. Om de traditionele klassen naar JavaScript te brengen, introduceert ES2015 standaard de class
syntaxis: een syntactische suiker over de prototypale overerving.,
Dit bericht maakt u vertrouwd met JavaScript-klassen: hoe u een klasse definieert, de instantie initialiseert, velden en methoden definieert, de private en publieke velden begrijpt, de statische velden en methoden begrijpt.
1. Definitie: class keyword
Het speciale sleutelwoord class
definieert een klasse in JavaScript:
class User { // The body of class}
de bovenstaande code definieert een klasse User
. De accolades { }
bepalen de klasse. Merk op dat deze syntaxis class declaration heet.,
u bent niet verplicht om de klassenaam aan te geven. Door een klasse-expressie te gebruiken kunt u de klasse toewijzen aan een variabele:
const UserClass = class { // The body of class};
u kunt eenvoudig een klasse exporteren als onderdeel van een ES2015-module. Hier is de syntaxis voor een standaard export:
export default class User { // The body of class}
en een named export:
export class User { // The body of class}
De klasse wordt nuttig wanneer u een instantie van de klasse maakt. Een instantie is een object met gegevens en gedrag beschreven door de klasse.,
de new
operator instantiseert de klasse in JavaScript: instance = new Class()
.
bijvoorbeeld, u kunt de User
klasse instantiate met behulp van de new
operator:
const myUser = new User();
new User()
maakt een instantie van de User
klasse.
2. Initialisatie: constructor ()
constructor(param1, param2, ...)
is een speciale methode in de body van een klasse die de instantie initialiseert., Dat is de plaats waar u de beginwaarden voor de velden instelt, of een willekeurige objectinstelling uitvoert.
In het volgende voorbeeld wordt de constructor-stelt de oorspronkelijke waarde van het veld name
:
class User { constructor(name) { this.name = name; }}
User
’s constructor heeft één parameter name
, die wordt gebruikt om de initiële waarde van het veld this.name
.
binnen de constructor this
waarde is gelijk aan de nieuw aangemaakte instantie.,
De argumenten die worden gebruikt om de klasse te instantiseren worden de parameters van de constructor:
class User { constructor(name) { name; // => 'Jon Snow' this.name = name; }}const user = new User('Jon Snow');
name
parameter in de constructor heeft de waarde 'Jon Snow'
.
Als u geen constructor voor de klasse definieert, wordt er een standaard gemaakt. De standaard constructor is een lege functie, die de instantie niet wijzigt.
tegelijkertijd kan een JavaScript-klasse maximaal één constructor hebben.
3. Velden
Klassenvelden zijn variabelen die informatie bevatten., Velden kan worden aangesloten op 2 entiteiten:
- Velden op de instantie van een klasse
- Velden van de klasse zelf (aka statische)
De velden hebben ook 2 niveaus van toegankelijkheid:
- Publiek: het veld is overal toegankelijk
- Privé: het gebied is alleen toegankelijk binnen de body van de klasse
3.1 Openbare instantie velden
Laten we opnieuw kijken naar de vorige code fragment:
class User { constructor(name) { this.name = name; }}
De expressie this.name = name
maakt een instantie veld name
en wijst naar een beginwaarde.,
Later kunt u name
veld Openen met behulp van een eigenschappenaccessor:
const user = new User('Jon Snow');user.name; // => 'Jon Snow'
name
is een publiek veld omdat u het buiten de User
klaslichaam.
wanneer de velden impliciet in de constructor worden gemaakt, zoals in het vorige scenario, kan het moeilijk zijn om de lijst met velden te begrijpen. Je moet ze ontcijferen uit de code van de constructeur.
een betere aanpak is om de klassenvelden expliciet te declareren., Het maakt niet uit wat constructor doet, de instantie heeft altijd dezelfde set van velden.
met het voorstel voor klassenvelden kunt u de velden in de body van de klasse definiëren. Bovendien kunt u meteen de beginwaarde aangeven:
class SomeClass { field1; field2 = 'Initial value'; // ...}
laten we de User
klasse wijzigen en een publiek veld declareren name
:
class User { name; constructor(name) { this.name = name; }}const user = new User('Jon Snow');user.name; // => 'Jon Snow'
name;
binnen het lichaam van de klasse verklaart een publiek veld name
.,
de openbare velden die op deze manier zijn gedeclareerd, zijn expressief: een snelle blik op de velden is voldoende om de gegevensstructuur van de klasse te begrijpen.
bovendien kan het class-veld direct worden geïnitialiseerd bij declaratie.
class User { name = 'Unknown'; constructor() { // No initialization }}const user = new User();user.name; // => 'Unknown'
name = 'Unknown'
binnen de klasse declareert een veld name
en initialiseert het met de waarde 'Unknown'
.
Er zijn geen beperkingen op de toegang of update van de openbare velden., U kunt lezen en waarden toewijzen aan openbare velden binnen de constructor, methoden, en buiten de klasse.
3.2 velden voor privé-instanties
inkapseling is een belangrijk concept waarmee u de interne details van een klasse kunt verbergen. Iemand die een ingekapselde klasse gebruikt, hangt alleen af van de publieke interface die de klasse biedt, en koppelt niet aan de implementatiedetails van de klasse.
klassen georganiseerd met encapsulatie in het achterhoofd zijn gemakkelijker bij te werken wanneer de details van de implementatie veranderen.,
een goede manier om interne gegevens van een object te verbergen is door de privé velden te gebruiken. Dit zijn de velden die alleen gelezen en gewijzigd kunnen worden binnen de klasse waartoe ze behoren. De buitenwereld van de klasse kan niet rechtstreeks van privé-velden veranderen.
De privévelden zijn alleen toegankelijk binnen de inhoud van de klasse.
Voer de veldnaam in met het speciale symbool #
om het privé te maken, bijvoorbeeld #myField
., Het voorvoegsel #
moet behouden blijven wanneer u met het veld werkt: declareren, lezen of wijzigen.
laten we ervoor zorgen dat het veld #name
eenmaal kan worden ingesteld bij de instantie initialisatie:
#name
is een privé veld. U kunt #name
openen en wijzigen binnen de body van User
. De methode getName()
(meer over methoden in de volgende sectie) kan toegang krijgen tot het privéveld #name
.,
maar als u probeert toegang te krijgen tot het privéveld #name
buiten User
class body, wordt een syntaxfout weergegeven: SyntaxError: Private field '#name' must be declared in an enclosing class
.
3.3 publieke statische velden
u kunt ook velden definiëren op de klasse zelf: de statische velden. Deze zijn handig om Klasse constanten te definiëren of informatie op te slaan die specifiek is voor de klasse.
om statische velden in een JavaScript-klasse aan te maken, gebruikt u het speciale trefwoord static
gevolgd door de veldnaam: static myStaticField
.,
laten we een nieuw veld toevoegen type
dat het gebruikerstype aangeeft: admin of regular. De statische velden TYPE_ADMIN
en TYPE_REGULAR
zijn handige constanten om de gebruikerstypen te onderscheiden:
static TYPE_ADMIN
en static TYPE_REGULAR
definieer statische variabelen binnen de User
klasse. Om toegang te krijgen tot de statische velden, moet u de klasse gebruiken, gevolgd door de veldnaam: User.TYPE_ADMIN
en User.TYPE_REGULAR
.
3.,4 Private statische velden
soms zijn zelfs de statische velden een implementatiedetail dat u wilt verbergen. In dit opzicht kunt u statische velden privé maken.
om het statische veld privé te maken, voegt u de veldnaam voor met #
speciaal symbool: static #myPrivateStaticField
.
stel dat u het aantal instanties van de User
Klasse wilt beperken., Om de details over instantiegrenzen te verbergen, kunt u de private statische velden aanmaken:
het statische veld User.#MAX_INSTANCES
stelt het maximum aantal toegestane instanties in, terwijl User.#instances
het statische veld telt het werkelijke aantal instanties.
Deze private statische velden zijn alleen toegankelijk binnen de User
klasse. Niets van de buitenwereld kan het limietmechanisme verstoren: dat is het voordeel van inkapseling.
4. Methoden
de velden bevatten gegevens., Maar de mogelijkheid om gegevens te wijzigen wordt uitgevoerd door speciale functies die deel uitmaken van de klasse: de methoden.
De JavaScript-klassen ondersteunen zowel instance-als statische methoden.
4.1 Instance methods
Instance methods kunnen instance data benaderen en wijzigen. Bijvoorbeeld methoden kunnen andere instantie methoden, evenals elke statische methode aanroepen.,
bijvoorbeeld, laten we een methode definiëren getName()
die de naam geeft in de User
klasse:
in een klasse methode, evenals in de constructor, this
waarde is gelijk aan de klasse instantie. Gebruik this
voor toegang tot instantiegegevens: this.field
, of roep andere methoden aan: this.method()
.,
laten we een nieuwe methode toevoegen nameContains(str)
die één parameter heeft en een andere methode aanroept:
nameContains(str) { ... }
is een methode van User
klasse die één parameter accepteert str
. Meer dan dat, voert het een andere methode uit van de instantie this.getName()
om de naam van de gebruiker te krijgen.
een methode kan ook privé zijn. Om de methode een privé-prefix te geven met #
.
laten we getName()
methode privé:
#getName()
is een privémethode., Binnen de methode nameContains(str)
noem je een privé methode zo: this.#getName()
.
omdat het privé is, kan #getName()
niet worden aangeroepen buiten User
class body.
4.2 Getters en setters
het getter en setter bootsen het reguliere veld na, maar met meer controle over hoe het veld wordt benaderd en gewijzigd.
de getter wordt uitgevoerd bij een poging om de veldwaarde te krijgen, terwijl setter bij een poging om een waarde in te stellen.,
om ervoor Te zorgen dat de name
eigendom van de User
niet leeg is, laat de wikkel de eigen veld #nameValue
in een getter en setter:
get name() {...}
getter wordt uitgevoerd wanneer u de waarde van het veld: user.name
.
4.3 statische methoden
de statische methoden zijn functies die direct aan de klasse zijn gekoppeld. Ze houden logica gerelateerd aan de klasse, in plaats van aan de instantie van de klasse.,
om een statische methode aan te maken gebruik het speciale trefwoord static
gevolgd door een reguliere methode syntaxis: static myStaticMethod() { ... }
.
bij het werken met statische methoden, zijn er 2 eenvoudige regels om te onthouden:
- Een statische methode kan toegang krijgen tot statische velden
- een statische methode kan geen toegang krijgen tot instantievelden.
bijvoorbeeld, laten we een statische methode maken die detecteert of een gebruiker met een specifieke naam al is genomen.,
isNameTaken()
is een statische methode die het statische privéveld User.#takenNames
gebruikt om te controleren op namen.
5. Overerving: breidt
de klassen in JavaScript-ondersteuning uit met behulp van hetextends
sleutelwoord.
In de uitdrukking class Child extends Parent { }
de Child
klasse erft van Parent
de constructor, velden en methoden.
bijvoorbeeld, laten we een nieuwe dochterklasse maken ContentWriter
die de ouderklasse uitbreidt User
.,
ContentWriter
erft van de User
de constructor, de methode getName()
en het veld name
. Ook verklaart de klasse ContentWriter
een nieuw veld posts
.
merk op dat privéleden van een ouderklasse niet worden overgenomen door de dochterklasse.
5.1 Parent constructor: super() in constructor()
Als u de parent constructor in een dochterklasse wilt aanroepen, moet u de speciale functie super()
gebruiken die beschikbaar is in de dochter-constructor.,
bijvoorbeeld, laten we ContentWriter
constructor de bovenliggende constructor van User
aanroepen, evenals het posts-veld initialiseren:
super(name)
binnen de dochterklasse ContentWriter
voert de constructor van de moederklasse User
.
merk op dat u in de dochter-constructor super()
moet uitvoeren voordat u this
sleutelwoord gebruikt. Het aanroepen van super()
zorgt ervoor dat de bovenliggende constructor de instantie initialiseert.,
class Child extends Parent { constructor(value1, value2) { // Does not work! this.prop2 = value2; super(value1); }}
5.2 Parent instance: super in methods
Als u toegang wilt krijgen tot de parent method binnenin een child method, kunt u de speciale sneltoets gebruiken super
.
getName()
van de dochterklasse ContentWriter
gebruikt de methode super.getName()
rechtstreeks vanuit de ouderklasse User
.
Deze functie wordt methode overschrijdend genoemd.
merk op dat u super
ook met statische methoden kunt gebruiken om toegang te krijgen tot de statische methoden van de ouder.
6., Object type checking: instanceof
object instanceof Class
is the operator that determines if object
is an instance of Class
.
Let’s see instanceof
operator in action:
user
is an instance of User
class, user instanceof User
evaluates to true
.
The empty object {}
is not an instance of User
, correspondingly obj instanceof User
is false
.,
instanceof
is polymorf: de operator detecteert een dochter als een instantie van de ouderklasse.
writer
is een instantie van de dochterklasse ContentWriter
. De operator writer instanceof ContentWriter
evalueert naar true
.
tegelijkertijd ContentWriter
is een dochterklasse van User
. Dus writer instanceof User
evalueert ook tot true
.
Wat als u de exacte klasse van de instantie wilt bepalen?, U kunt de eigenschap constructor
gebruiken en direct vergelijken met de klasse:
writer.constructor === ContentWriter; // => truewriter.constructor === User; // => false
7. Classes and prototypes
Ik moet zeggen dat de class syntaxis in JavaScript goed werk doet om te abstraheren van de prototypale overerving. Om de class
syntaxis te beschrijven heb ik niet eens de term prototype gebruikt.
maar de klassen zijn gebouwd bovenop de prototypale overerving. Elke klasse is een functie, en maakt een instantie wanneer aangeroepen als een constructor.
de volgende twee codefragmenten zijn equivalent.,
De class version:
de versie met prototype:
De class syntaxis is veel gemakkelijker te werken als u bekend bent met het klassieke overerving mechanisme van Java of Swift talen.
hoe dan ook, zelfs als je class syntaxis gebruikt in JavaScript, raad ik je aan om een goed begrip te hebben van prototypal inheritance.
8. Beschikbaarheid van Class features
De class features die in deze post worden gepresenteerd, zijn verdeeld over ES2015 en voorstellen in Fase 3.,
aan het einde van 2019 worden de class features opgesplitst in:
- publieke en private instance velden maken deel uit van Class fields proposal
- Private instance methods and accessors are part of Class private methods proposal
- publieke en private statische velden en private statische methoden maken deel uit van Class static features proposal
- de rest maakt deel uit van de ES2015 standaard.
9. Conclusie
JavaScript klassen initialiseren instanties met constructors, definiëren velden en methoden., U kunt velden en methoden toevoegen, zelfs op de klasse zelf met behulp van hetstatic
sleutelwoord.
overerving wordt bereikt met extends
trefwoord: u kunt eenvoudig een dochterklasse maken van een ouder. super
sleutelwoord wordt gebruikt om toegang te krijgen tot de ouderklasse vanuit een dochterklasse.
om gebruik te maken van encapsulation, maakt u de velden en methoden PRIVÉ om de interne details van uw klassen te verbergen. De namen van privévelden en methoden moeten beginnen met #
.,
de klassen in JavaScript worden steeds handiger in gebruik.
wat vindt u ervan om #
te gebruiken voor het voorvoegsel van privé-eigenschappen?