JavaScriptObiekty i klasy

#pole

Pola i metody z prefiksem # są prywatne: dostęp do nich ma wyłącznie kod wewnątrz klasy.

Na tej stronie

Przykład

#
JavaScript
class FuelTank {
  #fuel = 10

  use(amount) {
    if (amount > this.#fuel) return false
    this.#fuel -= amount
    return true
  }

  get fuel() {
    return this.#fuel
  }
}

const tank = new FuelTank()

console.log(tank.use(3))
console.log(tank.use(20))
console.log(tank.fuel)
console.log(tank)
console.log(Object.keys(tank))
Konsola
true
false
7
FuelTank {}
[]

Definicja i zastosowanie

#

Nazwa pola lub metody zaczynająca się od # oznacza składową prywatną. Można jej używać tylko w ciele klasy, w której ją zadeklarowano. Odwołanie obiekt.#pole z zewnątrz to błąd składni, zgłaszany, zanim kod w ogóle się uruchomi.

To prawdziwa prywatność, a nie tylko umowa, jak w przypadku konwencji z podkreśleniem _pole. Pola prywatne nie pojawiają się w Object.keys(), JSON.stringify() ani w pętli for...in, a kod spoza klasy nie może ich odczytać ani zmienić. Klasa sama decyduje, co udostępnia, np. przez metody albo gettery.

Pole prywatne trzeba zadeklarować w ciele klasy, np. #coins = 0 albo samo #password, zanim się go użyje. Prywatne mogą być też metody (#validate()), gettery i składowe statyczne. Klasy pochodne nie widzą pól prywatnych rodzica, a operator #pole in obiekt sprawdza, czy obiekt ma dane pole prywatne.

Składnia

#
Składnia
class Name {
  #field = value
  static #staticField = value

  #method() {}

  read() {
    return this.#field
  }

  static isName(obj) {
    return #field in obj
  }
}

Więcej przykładów

#
Prywatna metoda
JavaScript
class Account {
  #password

  constructor(login, password) {
    this.login = login
    this.#password = this.#hash(password)
  }

  #hash(text) {
    return [...text].reverse().join('')
  }

  checkPassword(attempt) {
    return this.#hash(attempt) === this.#password
  }
}

const account = new Account('ania', 'tajne123')

console.log(account.checkPassword('tajne123'))
console.log(account.checkPassword('haslo'))
console.log(JSON.stringify(account))
Konsola
true
false
{"login":"ania"}

Odwracanie napisu to tylko ilustracja. Prawdziwe hasła zabezpiecza się funkcjami skrótu po stronie serwera, a nie w przeglądarce.

Sprawdzanie przez #pole in
JavaScript
class Badge {
  #id

  constructor(id) {
    this.#id = id
  }

  static isBadge(value) {
    return #id in value
  }
}

console.log(Badge.isBadge(new Badge(7)))
console.log(Badge.isBadge({ id: 7 }))
Konsola
true
false
Pułapka: _pole to tylko umowa
JavaScript
class OldWallet {
  constructor() {
    this._coins = 100
  }
}

class NewWallet {
  #coins = 100
}

const oldWallet = new OldWallet()
oldWallet._coins = 1000000

console.log(oldWallet)
console.log(new NewWallet())
Konsola
OldWallet { _coins: 1000000 }
NewWallet {}

Podkreślenie tylko sugeruje, że pola nie należy ruszać, ale każdy kod może je zmienić. Pola #coins z zewnątrz nie da się nawet odczytać.

Obsługa przeglądarek

#

Szeroko dostępne · od 2021 roku

Działa we wszystkich nowoczesnych przeglądarkach, także na telefonach. Możesz używać bez obaw.

  • Chrome
  • Edge
  • Firefox
  • Safari

Dobre praktyki

#
  • Każde pole prywatne zadeklaruj w ciele klasy, zanim przypiszesz mu wartość. Samo this.#pole = x w konstruktorze, bez deklaracji, to błąd składni.
  • Pola prywatne nie trafiają do JSON.stringify() ani do kopii { ...obj }. Jeśli dane mają trafić do API, dodaj metodę toJSON(), która zwróci to, co chcesz wysłać.
  • Prywatność dotyczy klasy, a nie pojedynczego obiektu. Metoda klasy może odczytać #pole innej instancji tej samej klasy, np. przy porównaniu a.#id === b.#id.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.