Aanvullende functies van klassen in JavaScript
In dit artikel leggen we de aanvullende functies van klassen in JavaScript uit.
YouTube Video
Aanvullende functies van klassen in JavaScript
Privé-eigenschappen in JavaScript
In JavaScript zijn privé-eigenschappen eigenschappen die alleen toegankelijk zijn binnen het object of de klasse. Dit maakt een veiliger en robuuster ontwerp van de code mogelijk door middel van encapsulatie, zodat directe wijziging of toegang vanuit externe code niet mogelijk is.
In ECMAScript 2020 (ES11), geïntroduceerd in 2020, werd het gebruik van #
geïntroduceerd om privévelden binnen klassen te definiëren. Dit biedt een duidelijkere methode dan de traditionele JavaScript conventie voor privévelden (bijvoorbeeld variabelenamen die beginnen met een underscore). Dit biedt een duidelijkere methode, waarmee traditionele privésystemen in JavaScript (zoals variabelenamen die beginnen met een onderstrepingsteken) worden vervangen.
Hoe privé-eigenschappen te gebruiken
Privé-eigenschappen definiëren in klassen
Privévelden worden gedefinieerd met een naam die begint met #
. Dit veld kan niet rechtstreeks worden benaderd vanuit instanties van de klasse of de subklassen ervan.
1class Person {
2 // Define private property
3 #name;
4
5 constructor(name) {
6 this.#name = name;
7 }
8
9 // Method to access the private property
10 getName() {
11 return this.#name;
12 }
13
14 // Method to change the private property
15 setName(newName) {
16 this.#name = newName;
17 }
18}
19
20const john = new Person("John");
21console.log(john.getName()); // John
In de bovenstaande code is #name
een privé-eigenschap die niet direct toegankelijk is van buiten de Person
-klasse. Je kunt de naam alleen benaderen of wijzigen via de getName
- en setName
-methoden.
1// Cannot access private property directly
2console.log(john.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class
Privémethoden definiëren
Net als privé-eigenschappen worden privémethoden ook gedefinieerd met een naam die begint met #
. Privémethoden kunnen alleen worden aangeroepen vanuit de klasse.
1class Counter {
2 #count = 0;
3
4 increment() {
5 this.#count++;
6 this.#logCount(); // Calling private method
7 }
8
9 // Private method
10 #logCount() {
11 console.log(`Current count: ${this.#count}`);
12 }
13}
14
15const counter = new Counter();
16counter.increment(); // Current count: 1
#logCount
wordt hier gedefinieerd als een privémethode en kan niet worden benaderd van buiten de klasse. Deze methode wordt alleen gebruikt binnen de klasse.
1// Cannot access private method directly
2counter.#logCount(); // SyntaxError: Private field '#logCount' must be declared in an enclosing class
Voordelen en overwegingen van privé-eigenschappen
Voordeel
- Encapsulatie: Verbergt de interne status voor de buitenwereld en behoudt gegevensconsistentie.
- Beveiliging: Voorkomt dat eigenschappen onbedoeld worden gewijzigd door externe code.
- Verbeterde Onderhoudbaarheid: Verbergt de implementatie van objecten of klassen en verduidelijkt de interface die aan de buitenwereld wordt blootgesteld.
Notities
- Omdat private velden volledig verborgen blijven buiten de klasse, kunnen testen en debuggen moeilijk worden. Daarom is het belangrijk om een API te bieden die grondig getest kan worden tijdens de ontwerpfase.
- Private velden gedragen zich anders dan andere delen van JavaScript met prototype-gebaseerde kenmerken omdat ze uniek zijn voor elke instantie.
Traditionele pseudonieme implementatie van private eigenschappen
Voor de introductie van private velden met behulp van #
, had JavaScript geen officiële syntax voor private eigenschappen. Daarom werden pseudo-private eigenschappen in het verleden op de volgende manieren geïmplementeerd.
Conventie van het gebruik van underscores
Ontwikkelaars gaven conventioneel 'private' aan door variabelennamen te laten voorafgaan met een underscore.
1class Car {
2 constructor(brand) {
3 this._brand = brand; // Using an underscore to indicate private
4 }
5
6 getBrand() {
7 return this._brand;
8 }
9}
10
11const car = new Car("Toyota");
12console.log(car.getBrand()); // Toyota
13console.log(car._brand); // Toyota (Accessible from outside)
Deze methode is slechts een 'conventie', en in de praktijk kunnen de eigenschappen nog steeds van buitenaf worden geopend.
Implementatie van private eigenschappen met behulp van closures
Het is ook mogelijk om private eigenschappen te realiseren door closures te gebruiken met een functiebereik.
1function createPerson(name) {
2 let _name = name; // Private variable within function scope
3
4 return {
5 getName: function() {
6 return _name;
7 },
8 setName: function(newName) {
9 _name = newName;
10 }
11 };
12}
13
14const person = createPerson("Alice");
15console.log(person.getName()); // Alice
16person.setName("Bob");
17console.log(person.getName()); // Bob
18
19// Cannot access directly from outside
20console.log(person._name); // undefined
Met deze methode wordt de variabele _name
ingesloten binnen het functiebereik en kan deze niet direct van buitenaf worden benaderd.
Samenvatting
Private eigenschappen in JavaScript zijn zeer effectief bij het bieden van encapsulatie in klasse- en objectontwerp, waardoor gegevens veilig kunnen worden beschermd. De #
-notatie voor private velden die is geïntroduceerd in ES2020 biedt een duidelijkere en veiligere methode voor privacybeheer in vergelijking met traditionele conventies en closures.
Optionele chaining in JavaScript
Optionele ketting is een zeer nuttige syntax in JavaScript voor toegang tot diep geneste object eigenschappen. Het verbetert de leesbaarheid en onderhoudbaarheid van de code door veilige toegang mogelijk te maken zonder afzonderlijk te hoeven controleren op het bestaan van specifieke eigenschappen.
Basissyntax van optional chaining
Optionele ketting kan worden gebruikt door het plaatsen van een voordat de . Deze notatie retourneert undefined
wanneer een doorlopen eigenschap null
of undefined
is, waardoor het programma veilig kan blijven werken zonder een foutmelding te geven.
Voorbeeld:
1const user = {
2 name: 'John',
3 address: {
4 street: '123 Main St',
5 city: 'New York'
6 }
7};
8
9// Without using optional chaining
10const city = user && user.address && user.address.city;
11console.log(city); // New York
12
13// Using optional chaining
14const cityWithOptionalChaining = user?.address?.city;
15console.log(cityWithOptionalChaining); // New York
In dit voorbeeld benaderen we de address
en de eigenschap city
van het user
object. Zonder het gebruik van optional chaining moet je meerdere controles uitvoeren, maar met optional chaining kun je een eigenschap veilig benaderen met één enkele instructie.
Optional chaining gebruiken met arrays en functies
Optional chaining is niet alleen toepasbaar op objecteigenschappen, maar ook op array-elementen en functieaanroepen.
Voorbeeld met arrays:
1const users = [{ name: 'Alice' }, { name: 'Bob' }];
2
3// Accessing the non-existent third element
4const thirdUser = users[2]?.name;
5console.log(thirdUser); // undefined
- Op deze manier kun je ook toegang krijgen tot array-elementen met behulp van optionele chaining.
Voorbeeld met functies:
1const user = {
2 greet: function() {
3 return 'Hello!';
4 }
5};
6
7// Call the function only if greet exists
8const greeting = user.greet?.();
9console.log(greeting); // Hello!
10
11// Return undefined if greet does not exist
12const nonExistentGreeting = user.nonExistentMethod?.();
13console.log(nonExistentGreeting); // undefined
- Zoals in dit voorbeeld wordt getoond, kan het ook worden toegepast op functieverzoeken.
Optional chaining combineren met standaardwaarden
Bij het gebruik van optional chaining is het gebruikelijk om de logische OF (||
) of de nullish coalescing-operator (??
) te gebruiken om standaardwaarden te specificeren als een eigenschap niet bestaat.
Voorbeeld:
1const user = {
2 name: 'John',
3 address: {
4 city: 'New York'
5 }
6};
7
8// Set a default value for a non-existent property
9const state = user?.address?.state || 'Unknown';
10console.log(state); // Unknown
11
12// Example using the nullish coalescing operator
13const zipCode = user?.address?.zipCode ?? '00000';
14console.log(zipCode); // 00000
De logische OF-operator beschouwt waarden zoals false
, 0
en ''
als onwaar, terwijl de nullish coalescing-operator de standaardwaarde alleen gebruikt wanneer de waarde null
of undefined
is.
Voordelen van Optional Chaining
- Veilige toegang tot geneste objecten: Met optional chaining hoef je geen expliciete controles meer uit te voeren, wat de code beknopter maakt.
- Het vermijden van fouten: Het kan runtime-fouten voorkomen, zelfs als een eigenschap
null
ofundefined
is. - Verbeterde leesbaarheid en onderhoudbaarheid: Vooral bij het werken met veel geneste objecten wordt de leesbaarheid van de code sterk verbeterd.
Voorzichtigheden bij Optional Chaining
- Veelvuldig gebruik van optional chaining kan een teken zijn dat het ontwerp van de datastructuur te complex is. Het is aan te raden om te streven naar een eenvoudig datamodel.
- Aangezien sommige oudere browsers en JavaScript-engines dit niet ondersteunen, moet je mogelijk polyfills of transpilers gebruiken.
Conclusie
Optional chaining is een krachtige functie die veilige toegang tot eigenschappen en functies van geneste objecten in JavaScript vereenvoudigt. Het is bijzonder effectief bij toegang tot diep geneste datastructuren, wat bijdraagt aan foutpreventie en verbeterde leesbaarheid van de code.
Je kunt het bovenstaande artikel volgen met Visual Studio Code op ons YouTube-kanaal. Bekijk ook het YouTube-kanaal.