Sobes.tech
Middle+

Какво знаеш за дескрипторите?

sobes.tech AI

Отговор от AI

Дескрипторите в JavaScript са обекти, които описват различни свойства на обект, като стойността му (value), възможността за писане (writable), възможността за обхождане (enumerable) и възможността за конфигуриране (configurable). Има също дескриптори с гетъри и сетъри.

Има два типа дескриптори:

  • Данни дескриптори: съдържат стойността на свойството.

    • value: Стойността на свойството. Може да бъде всеки валиден тип данни.
    • writable: Логическа стойност. Ако е true, стойността на свойството може да бъде променена (obj.prop = newValue). По подразбиране false за accessor свойства и true за данни, създадени с обикновено присвояване.
    • enumerable: Логическа стойност. Ако е true, свойството ще бъде видимо при итерация през свойствата на обекта (например, в цикъл for...in или с Object.keys()). По подразбиране false за свойства, добавени с Object.defineProperty, и true за свойства, създадени с обикновено присвояване.
    • configurable: Логическа стойност. Ако е true, характеристиките на дескриптора (освен value и writable, когато се променят от данни към accessor) могат да бъдат променяни, а свойството да бъде изтрито. По подразбиране false за свойства, добавени с Object.defineProperty (освен value), и true за свойства, създадени с обикновено присвояване. След като е конфигурирано като не-конфигурируемо, не може да бъде променяно обратно. Можете да намалите writable от true на false, но не и обратното за не-конфигурируем getter/setter.
  • Accessor дескриптори: Определят функции, които ще бъдат извиквани при получаване (getter) или задаване (setter) на стойността на свойството.

    • get: Функция, която се извиква при четене на свойството. Резултатът от тази функция става стойността на свойството. Не приема аргументи.
    • set: Функция, която се извиква при запис в свойството. Приема един аргумент — новата зададена стойност.
    • enumerable: Логическа стойност (аналогично на data-дескрипторите).
    • configurable: Логическа стойност (аналогично на data-дескрипторите).

Дескрипторите не могат да се смесват: свойството има или value и writable, или get и set.

Дескрипторите се използват за управление на свойствата на обекта на по-ниско ниво, отколкото обикновеното присвояване, по-специално чрез методи като Object.defineProperty(), Object.defineProperties(), Object.getOwnPropertyDescriptor(), Object.getOwnPropertyDescriptors(), Object.create().

Пример за създаване на свойство с data-дескриптор:

// Създаваме празен обект
const obj = {};

// Определяме свойството 'name' с data-дескриптор
Object.defineProperty(obj, 'name', {
  value: 'Alice',
  writable: false, // Свойството не може да бъде променено
  enumerable: true, // Свойството ще бъде изброимо
  configurable: false // Характеристиките на свойството не могат да бъдат променяни, свойството не може да бъде изтрито
});

console.log(obj.name); // Ще изведе: Alice

// Опит за промяна на свойството (ще бъде игнорирано в строга режим или ще изхвърли грешка)
obj.name = 'Bob';
console.log(obj.name); // Ще изведе: Alice

// Опит за изтриване на свойството (ще бъде игнорирано или ще изхвърли грешка)
delete obj.name;
console.log(obj.name); // Ще изведе: Alice

Пример за създаване на свойство с accessor-дескриптор:

// Създаваме обект с частна променлива
const user = {
  _firstName: 'John', // Конвенционална частна променлива
  _lastName: 'Doe'
};

// Определяме свойството 'fullName' с accessor-дескриптор
Object.defineProperty(user, 'fullName', {
  get() {
    // Getter: връща пълното име
    return `${this._firstName} ${this._lastName}`;
  },
  set(value) {
    // Setter: разделя пълното име на части и актуализира частните променливи
    const parts = value.split(' ');
    this._firstName = parts[0];
    this._lastName = parts[1];
  },
  enumerable: true, // Ще бъде изброимо
  configurable: true // Характеристиките на свойството могат да бъдат променяни, свойството може да бъде изтрито
});

console.log(user.fullName); // Ще изведе: John Doe

user.fullName = 'Peter Pan';
console.log(user._firstName); // Ще изведе: Peter
console.log(user._lastName); // Ще изведе: Pan
console.log(user.fullName); // Ще изведе: Peter Pan

Използването на дескриптори позволява създаването на неизменяеми свойства, свойства с лениво изчисление, свойства с контрол на достъпа (getter/setter) и по-гъвкаво управление на поведението на обектите.