Skip to main content

Reflect.defineProperty()

Reflect.defineProperty() визначає (додає або змінює) властивість об'єкта із заданим дескриптором і повертає булеве значення, яке вказує, чи вдалося це зробити. Це сучасний аналог Object.defineProperty(), але з передбачуванішою та безпечнішою поведінкою: невдача тут є звичайним результатом, а не винятком.

Теорія

TL;DR

  • Синтаксис: Reflect.defineProperty(target, propertyKey, descriptor).
  • Повертає true при успіху і false при невдачі, а не сам об'єкт.
  • При невдачі не кидає виняток, тому try/catch не потрібен.
  • Приймає і data-дескриптор (value, writable), і accessor-дескриптор (get, set).
  • Ключі, це рядок або Symbol.
  • Основне застосування: безпечні перевірки, метапрограмування і пастки (traps) Proxy.

Швидкий приклад

javascript
const user = {}; const result = Reflect.defineProperty(user, 'name', { value: 'Maria', writable: true, enumerable: true, configurable: true }); console.log(result); // true console.log(user.name); // "Maria"

Те саме, що Object.defineProperty(user, 'name', { ... }), але з важливою відмінністю: Reflect не кидає помилку, а просто повертає false.

Сигнатура і аргументи

javascript
Reflect.defineProperty(target, propertyKey, descriptor)
АргументОпис
targetОб'єкт, у якому потрібно визначити властивість
propertyKeyІм'я властивості (рядок або Symbol)
descriptorДескриптор, тобто об'єкт з прапорцями (value, writable, enumerable, configurable, get, set)

Що повертає:

  • true, якщо властивість успішно визначено;
  • false, якщо операція не вдалася (наприклад, об'єкт захищений Object.freeze() або властивість неконфігурована).

Відмінність від Object.defineProperty()

ПоведінкаObject.defineProperty()Reflect.defineProperty()
Повертаєсам об'єктtrue / false
При помилцікидає винятокповертає false
Підходить длязвичайного кодубезпечних, «рефлективних» операцій

«Рефлективний» означає такий, що працює з внутрішніми властивостями об'єктів без викидання помилок.

Безпечна перевірка на практиці:

javascript
const frozen = Object.freeze({}); try { Object.defineProperty(frozen, 'x', { value: 1 }); } catch (e) { console.log('Error:', e.message); } console.log(Reflect.defineProperty(frozen, 'x', { value: 1 })); // false, без винятку

Reflect.defineProperty() просто поверне false замість того, щоб кидати виняток.

Дескриптори: data і accessor

Метод однаково працює і з data-, і з accessor-дескрипторами:

javascript
const person = {}; Reflect.defineProperty(person, 'fullName', { get() { return 'Maria Koval'; }, enumerable: true }); console.log(person.fullName); // "Maria Koval"

Тут властивість описана геттером, а не значенням, і Reflect.defineProperty() приймає такий дескриптор без жодних застережень.

Динамічне визначення властивостей і умовні перевірки

Метод зручно викликати в циклі, коли набір ключів відомий лише під час виконання:

javascript
const obj = {}; ['name', 'age', 'city'].forEach(key => { Reflect.defineProperty(obj, key, { value: key.toUpperCase(), enumerable: true }); }); console.log(obj); // { name: 'NAME', age: 'AGE', city: 'CITY' }

Повернене значення корисне прямо в умові:

javascript
if (Reflect.defineProperty(user, 'role', { value: 'admin' })) { console.log('Property added successfully'); } else { console.log('Failed to add property'); }

Це зручно саме тим, що не вимагає try/catch: результат перевіряється як звичайний булевий вираз.

Взаємодія з Proxy

У пастці (trap) defineProperty об'єкта Proxy метод Reflect.defineProperty використовують, щоб делегувати поведінку за замовчуванням:

javascript
const target = {}; const proxy = new Proxy(target, { defineProperty(target, key, descriptor) { console.log(`Defining property "${String(key)}"`); return Reflect.defineProperty(target, key, descriptor); } }); proxy.x = 10; // під капотом автоматично викликає Reflect.defineProperty

У Proxy рефлективні методи (Reflect.*) допомагають реалізувати поведінку максимально природно: сигнатура пастки збігається з сигнатурою відповідного методу Reflect, а булевий результат, це саме те, що пастка має повернути.

Підсумкова таблиця:

ПитанняВідповідь
Що робитьВизначає (створює або змінює) властивість об'єкта із вказаним дескриптором
Що повертаєtrue при успіху, false при невдачі
Чи кидає помилкиНі
Чи використовує дескрипторТак (value, writable, configurable, enumerable, get, set)
Де застосовуєтьсяБезпечні операції, Proxy, метапрограмування

Типові помилки

  • Очікувати, що метод поверне об'єкт. Object.defineProperty() повертає сам об'єкт і тому ланцюжкується, а Reflect.defineProperty() повертає true / false. Запис Reflect.defineProperty(obj, 'a', d).b зламається.
  • Ігнорувати повернене значення. Оскільки винятку немає, мовчазна невдача проходить непоміченою. Якщо результат важливий, його треба перевіряти.
  • Обгортати виклик у try/catch «про всяк випадок». Для помилки визначення властивості це зайве: сенс Reflect саме в тому, щоб обійтися без винятку. Виняток тут можливий хіба що для некоректних аргументів, наприклад коли target не є об'єктом.
  • Забувати, що прапорці за замовчуванням дорівнюють false. Дескриптор { value: 1 } створює властивість, яка не є writable, enumerable чи configurable, тож вона не потрапить у Object.keys() і не зміниться присвоєнням.
  • Плутати з Reflect.getOwnPropertyDescriptor(). Перший метод встановлює дескриптор, другий читає його.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.