Дополнительные возможности классов в JavaScript

Дополнительные возможности классов в JavaScript

В этой статье мы объясним дополнительные возможности классов в JavaScript.

YouTube Video

Дополнительные возможности классов в JavaScript

Приватные свойства в JavaScript

В JavaScript приватные свойства — это свойства, которые доступны только внутри объекта или класса. Это обеспечивает более безопасный и надежный дизайн кода за счет инкапсуляции, исключающей возможность прямого изменения или ссылки из внешнего кода.

В ECMAScript 2020 (ES11) была введена возможность использования символа # (хеш) для объявления приватных полей внутри класса. Это обеспечивает более понятный подход, заменяя традиционные соглашения JavaScript о приватности (например, имена переменных, начинающиеся с подчеркивания).

Преимущества приватных свойств

Следующие преимущества частных свойств.

  • Инкапсуляция: Скрывает внутреннее состояние от внешнего мира и поддерживает согласованность данных.
  • Безопасность: Предотвращает случайное изменение свойств внешним кодом.
  • Улучшенная поддерживаемость: Скрывает реализацию объектов или классов и уточняет интерфейс, открытый для внешнего мира.

Как использовать приватные свойства

Определение приватных свойств в классах

Приватные поля определяются с использованием имени, начинающегося с #. Доступ к этому полю не может быть получен напрямую из экземпляров класса или его подклассов.

 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

В приведенном выше коде #name — это приватное свойство, которое недоступно для прямого доступа извне класса Person. Вы можете получить доступ или изменить имя только через методы getName и setName.

Определение приватных методов

Как и приватные свойства, приватные методы также определяются с использованием имени, начинающегося с #. Приватные методы могут вызываться только внутри класса.

 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

Здесь #logCount определяется как приватный метод и недоступен извне класса. Этот метод используется только внутри класса.

Преимущества и соображения использования приватных свойств

Преимущество

  • Поскольку к нему нельзя получить доступ напрямую извне класса, предотвращаются непреднамеренные изменения или действия.
  • Поскольку части, невидимые снаружи, могут быть хорошо скрыты, вы можете четко управлять тем, какие части вы предоставляете как API.

Примечания

  • Поскольку приватные поля полностью скрыты от внешнего доступа, тестирование и отладка могут стать сложными. Следовательно, важно предоставить API, который можно тщательно протестировать на этапе проектирования.
  • Приватные поля ведут себя иначе, чем другие части JavaScript с характеристиками на основе прототипов, поскольку они уникальны для каждого экземпляра.

Традиционная псевдонимная реализация приватных свойств

До введения приватных полей с использованием # в JavaScript не существовало официального синтаксиса для приватных свойств. Поэтому в прошлом псевдоприватные свойства реализовывались следующими способами.

Конвенция использования подчеркиваний

Разработчики условно указывали 'приватность', добавляя подчеркивание в начале имени переменной.

 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)

Этот метод является лишь 'конвенцией', и на практике к таким свойствам все равно можно получить доступ извне.

Реализация приватных свойств с использованием замыканий

Также можно создать приватные свойства с использованием замыканий в области видимости функции.

 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

При таком методе переменная _name заключена в область видимости функции и не может быть напрямую доступна извне.

Резюме

Приватные свойства в JavaScript очень эффективны для обеспечения инкапсуляции в проектировании классов и объектов, помогая надежно защищать данные. Обозначение # для приватных полей, введенное в ES2020, предоставляет более четкий и безопасный способ управления приватностью по сравнению с традиционными конвенциями и замыканиями.

Опциональная цепочка в JavaScript

Опциональная цепочка — это очень полезный синтаксис в JavaScript для доступа к свойствам глубоко вложенных объектов. Это повышает читаемость и поддерживаемость кода, позволяя безопасно получить доступ без необходимости проверять наличие конкретных свойств.

Основной синтаксис опциональной цепочки

Опциональная цепочка используется путем добавления ? перед точкой (.) или записью в скобках при доступе к свойствам. Эта нотация возвращает undefined, если встреченное свойство является null или undefined, что позволяет программе продолжать выполнение без ошибки.

Пример:

 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

В этом примере мы получаем доступ к свойству address и его свойству city объекта user. Без использования опциональной цепочки вам нужно было бы выполнять несколько проверок существования, но с опциональной цепочкой вы можете безопасно получить доступ к свойству одной строкой.

Использование опциональной цепочки с массивами и функциями

Опциональная цепочка применяется не только к свойствам объектов, но и к элементам массивов и вызовам функций.

Пример с массивами:

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

Пример с функциями:

 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

Объединение опциональной цепочки с значениями по умолчанию

При использовании опциональной цепочки часто используют логический оператор ИЛИ (||) или оператор слияния с null (??) для задания значений по умолчанию, если свойство не существует.

Пример:

 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

Оператор || воспринимает false, 0, '' и т.п. как ложные значения, тогда как оператор ?? использует значение по умолчанию только в случае, если операнд равен null или undefined.

Преимущества опциональной цепочки

  • Безопасный доступ к вложенным объектам: Используя опциональную цепочку, вам больше не нужно выполнять явные проверки существования, что делает код более лаконичным.
  • Избежание ошибок: Это позволяет избежать ошибок времени выполнения, даже если свойство имеет значение null или undefined.
  • Улучшение читаемости и сопровождения: Особенно при работе с множеством вложенных объектов, читаемость кода значительно улучшается.

Предостережения при использовании опциональной цепочки

  • Частое использование опциональной цепочки может быть признаком чрезмерно сложной структуры данных. Следует стремиться к простой модели данных.
  • Поскольку некоторые старые браузеры и JavaScript-движки не поддерживают её, возможно, потребуется использовать полифиллы или транспилеры.

Заключение

Опциональная цепочка — это мощная функция, которая упрощает безопасный доступ к свойствам и функциям вложенных объектов в JavaScript. Она особенно эффективна при доступе к глубоко вложенным структурам данных, способствуя предотвращению ошибок и улучшению читаемости кода.

Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.

YouTube Video