Публічні та приватні поля класу у JavaScript

4 хв. читання

Розглядаємо новий синтаксис оголошення публічних полів класу у V8 та Chrome 72, а також знайомимось зі синтаксисом приватних полів, що очікується незабаром.

У цьому коді ми створюємо екземпляр класу під назвою IncreasingCounter:

const counter = new IncreasingCounter();
counter.value;
// Вивід 'Getting the current value!'
// → 0
counter.increment();
counter.value;
// Вивід 'Getting the current value!'
// → 1

Помітьте, що при отриманні значення value виконується певний код (виводиться повідомлення). Це відбувається до повернення результату. Вас може цікавити: як реалізувати такий клас у JavaScript? 🤔

Синтаксис класів ES2015

Саме так ми можемо реалізувати IncreasingCounter з синтаксисом класів ES2015:

class IncreasingCounter {
  constructor() {
    this._count = 0;
  }
  get value() {
    console.log('Getting the current value!');
    return this._count;
  }
  increment() {
    this._count++;
  }
}

Клас встановлює гетер для value та метод increment для прототипу. Цікаво, що клас має конструктор, який створює властивість екземпляру _count та встановлює її значення за замовчуванням як 0. Тут ми використали нижнє підкреслення, щоб позначити, що властивість _count не повинна прямо використовуватись споживачами класів. Ця властивість зі спеціальною семантикою мови насправді не «приватна».

const counter = new IncreasingCounter();
counter.value;
// Виводить 'Getting the current value!'
// → 0

// Ніщо не завадить отримати чи зіпсувати значення
// `_count`. 😢
counter._count;
// → 0
counter._count = 42;
counter.value;
// Виводить 'Getting the current value!'
// → 42

Публічні поля класу

Спростити визначення класу можна з новим синтаксисом публічних полів:

class IncreasingCounter {
  _count = 0;
  get value() {
    console.log('Getting the current value!');
    return this._count;
  }
  increment() {
    this._count++;
  }
}

Властивість _count тепер оголошена на початку класу. Нам більше не потрібно створювати конструктор лише для визначення декількох полів. Так код виглядає чистішим.

Однак, поле _count досі публічне. У нашому прикладі ми хочемо обмежити прямий доступ до властивості.

Приватні поля класу

На допомогу приходять приватні поля класу. Новий синтаксис їх оголошення подібний до публічних полів: вам лише треба позначити поле символом #. Вважайте # частиною назви поля:

class IncreasingCounter {
  #count = 0;
  get value() {
    console.log('Getting the current value!');
    return this.#count;
  }
  increment() {
    this.#count++;
  }
}

Ми не можемо отримати доступ до приватних полів поза тілом класу:

const counter = new IncreasingCounter();
counter.#count;
// → Синтаксична помилка
counter.#count = 42;
// → Синтаксична помилка

Публічні та статичні властивості

Синтаксис полів класу стане у пригоді для створення публічних та приватних статичних властивостей і методів. Це виглядає так:

class FakeMath {
  // `PI` - статична публічна властивість
  static PI = 22 / 7; // Достатньо близьке значення

  // `#totallyRandomNumber`- статична приватна властивість
  static #totallyRandomNumber = 4;

  // `#computeRandomNumber` - статичний приватний метод
  static #computeRandomNumber() {
    return FakeMath.#totallyRandomNumber;
  }

  // `random` - статичний публічний метод (ES2015 синтаксис)
  // що використовує `#computeRandomNumber`.
  static random() {
    console.log('I heard you like random numbers…')
    return FakeMath.#computeRandomNumber();
  }
}

FakeMath.PI;
// → 3.142857142857143
FakeMath.random();
// Виводить 'I heard you like random numbers…'
// → 4
FakeMath.#totallyRandomNumber;
// → Синтаксична помилка
FakeMath.#computeRandomNumber();
// → Синтаксична помилка

Простіші підкласи

Переваги синтаксису полів класу стають ще зрозумілішими, коли ми маємо справу з підкласами, які вводять додаткові поля. Уявіть наступний базовий клас Animal:

class Animal {
  constructor(name) {
    this.name = name;
  }
}

Створимо його підклас Cat, який вводитиме додаткові властивості. Для цього спершу треба вказати super() для виклику конструктора базового класу Animal перед створенням властивості:

class Cat extends Animal {
  constructor(name) {
    super(name);
    this.likesBaths = false;
  }
  meow() {
    console.log('Meow!');
  }
}

Тут ми використовуємо багато шаблонного коду просто, щоб вказати, що коти не люблять купатися. На щастя, із синтаксисом полів класу зникає потреба у конструкторі з викликом super():

class Cat extends Animal {
  likesBaths = false;
  meow() {
    console.log('Meow!');
  }
}

Публічні поля класу з'явилися у V8 v7.2 та Chrome 72. У найближчих планах також реалізація приватних полів класу.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.2K
Приєднався: 9 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація