Ytterligare funktioner för klasser i JavaScript

Ytterligare funktioner för klasser i JavaScript

I denna artikel kommer vi att förklara de ytterligare funktionerna för klasser i JavaScript.

YouTube Video

Ytterligare funktioner för klasser i JavaScript

Privata egenskaper i JavaScript

I JavaScript är privata egenskaper sådana som endast är tillgängliga inom objektet eller klassen. Detta möjliggör en säkrare och mer robust koddesign genom att tillhandahålla kapsling, så att direkt modifiering eller referens från extern kod inte är möjlig.

Introducerades i ECMAScript 2020 (ES11) år 2020, användningen av # (hash) för att definiera privata fält inom en klass infördes. Detta ger ett tydligare sätt, som ersätter traditionella JavaScript-konventioner för privata fält (såsom variabelnamn som börjar med ett understreck).

Fördelar med privata egenskaper

Följande är fördelarna med privata egenskaper.

  • Inkapsling: Döljer det interna tillståndet från utsidan och bibehåller datakonsistens.
  • Säkerhet: Förhindrar att egenskaper oavsiktligt ändras av extern kod.
  • Förbättrad underhållbarhet: Döljer implementeringen av objekt eller klasser och klargör det gränssnitt som exponeras utåt.

Hur man använder privata egenskaper

Definiera privata egenskaper i klasser

Privata fält definieras med ett namn som börjar med #. Detta fält kan inte direkt nås från instanser av klassen eller dess underklasser.

 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
22
23// Cannot access private property directly
24console.log(john.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class

I koden ovan är #name en privat egenskap som inte kan nås direkt utanför Person-klassen. Du kan endast komma åt eller ändra namnet genom metoderna getName och setName.

Definiera privata metoder

Precis som privata egenskaper definieras även privata metoder med ett namn som börjar med #. Privata metoder kan endast anropas inom klassen.

 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
17
18// Cannot access private method directly
19counter.#logCount(); // SyntaxError: Private field '#logCount' must be declared in an enclosing class

Här definieras #logCount som en privat metod och kan inte nås utanför klassen. Denna metod används endast inom klassen.

Fördelar och överväganden med privata egenskaper

Fördel

  • Eftersom det inte kan nås direkt utanför klassen förhindras oavsiktliga ändringar eller operationer.
  • Eftersom delar som inte är synliga från utsidan kan döljas väl, kan du tydligt hantera de delar du exponerar som ett API.

Anteckningar

  • Eftersom privata fält är helt dolda från utsidan av klassen kan testning och felsökning bli svåra. Därför är det viktigt att tillhandahålla ett API som kan testas grundligt i designfasen.
  • Privata fält beter sig annorlunda än andra delar av JavaScript med prototypbaserade egenskaper eftersom de är unika för varje instans.

Traditionellt pseudonymt genomförande av privata egenskaper

Innan introduktionen av privata fält med # hade JavaScript ingen officiell syntax för privata egenskaper. Därför implementerades pseudo-privata egenskaper tidigare på följande sätt.

Konvention av att använda understreck

Utvecklare indikerade konventionellt 'privat' genom att lägga till ett understreck före variabelnamn.

 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)

Denna metod är endast en 'konvention', och i praktiken kan egenskaperna fortfarande nås från utsidan.

Implementering av privata egenskaper med hjälp av closures

Det är också möjligt att uppnå privata egenskaper genom att använda closures med funktionsscope.

 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

Med denna metod är variabeln _name innesluten inom funktionsscope och kan inte nås direkt från utsidan.

Sammanfattning

Privata egenskaper i JavaScript är mycket effektiva för att tillhandahålla kapsling i klass- och objektutformning, vilket hjälper till att skydda data säkert. Den #-notation för privata fält som introducerades i ES2020 ger en tydligare och säkrare metod för hantering av integritet jämfört med traditionella konventioner och closures.

Optional Chaining i JavaScript

Optional Chaining är en mycket användbar syntax i JavaScript för att nå egenskaper hos djupt inbäddade objekt. Den förbättrar kodläsbarhet och underhållbarhet genom att tillåta säker åtkomst utan att behöva kontrollera förekomsten av specifika egenskaper individuellt.

Grundläggande syntax för Optional Chaining

Optional Chaining kan användas genom att placera ? före punkten (.) eller hakparentessyntaxen som används för att nå egenskaper. Denna notation returnerar undefined när en traverserad egenskap är null eller undefined, vilket gör att programmet kan fortsätta bearbetningen säkert utan att generera ett fel.

Exempel:

 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

I detta exempel når vi address och dess city-egenskap hos user-objektet. Utan att använda valfri kedjning skulle du behöva utföra flera existenskontroller, men med valfri kedjning kan du säkert få åtkomst till egenskapen med en enda sats.

Använda valfri kedjning med arrayer och funktioner

Valfri kedjning gäller inte bara för objektens egenskaper, utan även för arrayelement och funktionsanrop.

Exempel med arrayer:

1const users = [{ name: 'Alice' }, { name: 'Bob' }];
2
3// Accessing the non-existent third element
4const thirdUser = users[2]?.name;
5console.log(thirdUser);  // undefined

Exempel med funktioner:

 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

Kombinera valfri kedjning med standardvärden

När du använder valfri kedjning är det vanligt att använda den logiska ELLER-operatorn (||) eller nullish sammanslagningsoperatorn (??) för att ange standardvärden om en egenskap inte existerar.

Exempel:

 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

||-operatorn behandlar false, 0, '', etc., som falska, medan ??-operatorn endast använder standardvärdet om operanden är null eller undefined.

Fördelar med valfri kedjning

  • Säker åtkomst till nästlade objekt: Genom att använda valfri kedjning behöver du inte längre utföra explicita existenskontroller, vilket gör koden mer kortfattad.
  • Undvikande av fel: Det kan förhindra körningsfel även om en egenskap är null eller undefined.
  • Förbättrad läsbarhet och underhållbarhet: Särskilt när man hanterar många nästlade objekt förbättras kodens läsbarhet avsevärt.

Försiktighet vid användning av valfri kedjning

  • Frekvent användning av valfri kedjning kan vara ett tecken på att datastrukturens design är alltför komplex. Du bör sträva efter en enkel datamodell.
  • Eftersom vissa äldre webbläsare och JavaScript-motorer inte stöder det kan du behöva använda polyfills eller transpilers.

Slutsats

Valfri kedjning är en kraftfull funktion som förenklar säker åtkomst till egenskaper och funktioner hos nästlade objekt i JavaScript. Det är särskilt effektivt vid åtkomst till djupt nästlade datastrukturer, vilket bidrar till att förebygga fel och förbättra kodens läsbarhet.

Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.

YouTube Video