Дополнительные возможности классов в 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-канал.