Sobes.tech
Middle+

Co wiesz o deskryptorach?

sobes.tech AI

Odpowiedź od AI

Deskriptorzy w JavaScript to obiekty opisujące różne właściwości właściwości obiektu, takie jak jej wartość (value), możliwość zapisu (writable), możliwość enumeracji (enumerable) i możliwość konfigurowania (configurable). Istnieją również deskriptor z getterami i setterami.

Istnieją dwa typy deskriptorów:

  • Deskriptorzy danych: Zawierają wartość właściwości.

    • value: Wartość właściwości. Może być dowolnym poprawnym typem danych.
    • writable: Wartość logiczna. Jeśli true, wartość właściwości może być zmieniona (obj.prop = nowaWartość). Domyślnie false dla właściwości dostępu i true dla właściwości danych tworzonych zwykłym przypisaniem.
    • enumerable: Wartość logiczna. Jeśli true, właściwość będzie widoczna podczas iteracji po właściwościach obiektu (np. w pętli for...in lub przy użyciu Object.keys()). Domyślnie false dla właściwości dodanych przez Object.defineProperty i true dla właściwości tworzonych zwykłym przypisaniem.
    • configurable: Wartość logiczna. Jeśli true, cechy deskriptorów (z wyjątkiem value i writable przy zmianie z danych na dostępowe) mogą być modyfikowane, a sama właściwość może być usunięta. Domyślnie false dla właściwości dodanych przez Object.defineProperty (z wyjątkiem value) i true dla właściwości tworzonych zwykłym przypisaniem. Po skonfigurowaniu jako niekonfigurowalny, nie można tego zmienić z powrotem. Możesz zmniejszyć writable z true na false, ale nie odwrotnie na niekonfigurowalnym getterze/setterze.
  • Deskriptorzy dostępowe: Definiują funkcje wywoływane przy odczycie (getter) lub ustawieniu (setter) wartości właściwości.

    • get: Funkcja wywoływana przy odczycie właściwości. Wynik tej funkcji staje się wartością właściwości. Nie przyjmuje argumentów.
    • set: Funkcja wywoływana przy zapisie do właściwości. Przyjmuje jeden argument — nową ustawianą wartość.
    • enumerable: Wartość logiczna (podobnie jak w deskriptorach danych).
    • configurable: Wartość logiczna (podobnie jak w deskriptorach danych).

Deskriptorów nie można mieszać: właściwość ma albo value i writable, albo get i set.

Deskriptorzy służą do zarządzania właściwościami obiektu na niższym poziomie niż zwykłe przypisanie, w szczególności przez metody Object.defineProperty(), Object.defineProperties(), Object.getOwnPropertyDescriptor(), Object.getOwnPropertyDescriptors(), Object.create().

Przykład tworzenia właściwości z deskriptorami danych:

// Tworzymy pusty obiekt
const obj = {};

// Definiujemy właściwość 'name' z deskriptorem danych
Object.defineProperty(obj, 'name', {
  value: 'Alice',
  writable: false, // Właściwość nie może być zmieniona
  enumerable: true, // Właściwość będzie widoczna podczas iteracji
  configurable: false // Cechy właściwości nie mogą być zmienione, właściwość nie może być usunięta
});

console.log(obj.name); // Wyświetli: Alice

// Próba zmiany właściwości (zostanie zignorowana w trybie ścisłym lub spowoduje błąd)
obj.name = 'Bob';
console.log(obj.name); // Wyświetli: Alice

// Próba usunięcia właściwości (zostanie zignorowana lub spowoduje błąd)
delete obj.name;
console.log(obj.name); // Wyświetli: Alice

Przykład tworzenia właściwości z deskriptorem dostępów:

// Tworzymy obiekt z prywatną zmienną
const user = {
  _firstName: 'John', // Zmienna prywatna według konwencji
  _lastName: 'Doe'
};

// Definiujemy właściwość 'fullName' z deskriptorem dostępów
Object.defineProperty(user, 'fullName', {
  get() {
    // Getter: zwraca pełne imię
    return `${this._firstName} ${this._lastName}`;
  },
  set(value) {
    // Setter: dzieli pełne imię na części i aktualizuje prywatne zmienne
    const parts = value.split(' ');
    this._firstName = parts[0];
    this._lastName = parts[1];
  },
  enumerable: true, // Właściwość będzie widoczna podczas iteracji
  configurable: true // Cechy właściwości mogą być zmienione, właściwość może być usunięta
});

console.log(user.fullName); // Wyświetli: John Doe

user.fullName = 'Peter Pan';
console.log(user._firstName); // Wyświetli: Peter
console.log(user._lastName); // Wyświetli: Pan
console.log(user.fullName); // Wyświetli: Peter Pan

Użycie deskriptorów pozwala tworzyć właściwości niemutowalne, właściwości z leniwym obliczaniem, właściwości z kontrolą dostępu (getter/setter) i bardziej elastycznie zarządzać zachowaniem obiektów.