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:

  1. Velden op de instantie van een klasse
  2. Velden van de klasse zelf (aka statische)

De velden hebben ook 2 niveaus van toegankelijkheid:

  1. Publiek: het veld is overal toegankelijk
  2. 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:

  1. Een statische methode kan toegang krijgen tot statische velden
  2. 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?