Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Об'єкт Reflect». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`Reflect` це вбудований об'єкт з набором допоміжних методів для роботи з об'єктами: читання і запис властивостей, їх видалення й оголошення, виклик функцій і створення екземплярів.** Простіше кажучи, це набір «безпечних» аналогів операторів JavaScript (`in`, `delete`, `[]`, `Object.defineProperty()` і подібних), зібраних в одному місці. Замість того щоб кидати помилку, коли операція неможлива, більшість методів просто повертають `true` або `false`. Найчастіше `Reflect` використовують усередині пасток `Proxy`, щоб делегувати стандартну поведінку назад на оригінальний об'єкт із коректним `this`. ```javascript const user = { name: 'Tim' }; Reflect.set(user, 'age', 25); Reflect.has(user, 'age'); // true ``` **Ключове:** `Reflect` це єдиний, передбачуваний інтерфейс до низькорівневих операцій над об'єктами, ідеальна пара до `Proxy`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`Reflect` це вбудований об'єкт, який містить набір допоміжних методів для роботи з об'єктами: доступ до властивостей, їх видалення, створення, виклик функцій і таке інше.** Простіше кажучи, `Reflect` це набір «безпечних» аналогів операторів JavaScript (`in`, `delete`, `[]`, `Object.defineProperty()` і подібних), зібраний в одному місці. ## Теорія ### TL;DR - `Reflect` це вбудований об'єкт, не функція і не конструктор: `new Reflect()` неможливий. - Він дає єдиний інтерфейс до низькорівневих операцій над об'єктами. - Його методи повертають `true` або `false` замість того, щоб кидати помилку, коли операція неможлива. - Кожній пастці `Proxy` відповідає однойменний метод `Reflect` з такою самою сигнатурою. - Усередині пасток `Reflect` гарантує коректну передачу `this` через аргумент `receiver`. ### Швидкий приклад ```javascript const user = { name: 'Tim' }; console.log(Reflect.get(user, 'name')); // 'Tim' Reflect.set(user, 'age', 25); console.log(user); // { name: 'Tim', age: 25 } console.log(Reflect.has(user, 'age')); // true Reflect.deleteProperty(user, 'age'); console.log(Reflect.has(user, 'age')); // false ``` ### Основні цілі Reflect 1. **Єдиний інтерфейс** для низькорівневих операцій над об'єктами, замість різних операторів і функцій (`delete`, `in`, `Object.defineProperty` і так далі). 2. **Робота в парі з `Proxy`**, щоб можна було делегувати дії назад на оригінальний об'єкт. 3. **Передбачуваніша поведінка**: методи повертають `true` або `false`, не кидаючи помилок, якщо операція неможлива. ### Популярні методи Reflect | Метод | Що робить | Аналог без Reflect | | --- | --- | --- | | `Reflect.get(obj, prop)` | Повертає значення властивості | `obj[prop]` | | `Reflect.set(obj, prop, value)` | Встановлює значення властивості | `obj[prop] = value` | | `Reflect.has(obj, prop)` | Перевіряє наявність властивості | `'prop' in obj` | | `Reflect.deleteProperty(obj, prop)` | Видаляє властивість | `delete obj[prop]` | | `Reflect.ownKeys(obj)` | Повертає всі ключі, включно з `Symbol` | `Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj))` | | `Reflect.defineProperty(obj, prop, desc)` | Оголошує властивість | `Object.defineProperty(obj, prop, desc)` | | `Reflect.getOwnPropertyDescriptor(obj, prop)` | Отримує дескриптор властивості | `Object.getOwnPropertyDescriptor(obj, prop)` | | `Reflect.apply(fn, thisArg, argsArray)` | Викликає функцію з контекстом і аргументами | `fn.apply(thisArg, argsArray)` | | `Reflect.construct(fn, argsArray)` | Створює екземпляр, як `new fn(...)` | `new fn(...argsArray)` | ### Reflect і Proxy разом `Reflect` часто використовують усередині пасток `Proxy`, щоб «пробросити» стандартну поведінку назад до цільового об'єкта (`target`). ```javascript const user = { name: 'Tim' }; const proxy = new Proxy(user, { get(target, prop, receiver) { console.log(`Reading property: ${prop}`); // замість target[prop] безпечніше так: return Reflect.get(target, prop, receiver); }, set(target, prop, value, receiver) { console.log(`Writing property: ${prop} = ${value}`); return Reflect.set(target, prop, value, receiver); } }); proxy.name; // log: Reading property: name proxy.age = 30; // log: Writing property: age = 30 ``` Чому так роблять? Тому що `Reflect` гарантує коректну передачу `this` і внутрішнього контексту, на відміну від прямого звертання через `target[prop]`. Крім того, `Reflect.set` повертає готовий `true` або `false`, який пастка `set` і зобов'язана повернути. ### Підсумок | Пункт | Опис | | --- | --- | | `Reflect` | Вбудований об'єкт з методами для роботи з об'єктами | | Мета | Уніфікувати низькорівневі операції (читання, запис, видалення, створення тощо) | | Особливість | Безпечні аналоги операторів, що повертають `true` або `false` замість помилок | | Часто використовується | Усередині пасток `Proxy` | ### Типові помилки - **Викликати `Reflect` як функцію або конструктор.** Це звичайний об'єкт-простір імен, `new Reflect()` кидає `TypeError`. - **Плутати `Reflect.defineProperty` з `Object.defineProperty`.** Перший повертає `false`, другий кидає `TypeError`; саме тому в пастках зручніший `Reflect`. - **Забувати передати `receiver` у `Reflect.get` і `Reflect.set`.** Без нього геттери і сеттери з прототипа отримають неправильний `this`. - **Вважати, що `Reflect.ownKeys` повертає лише рядкові ключі.** Він віддає і символи, і невичислювані (non-enumerable) властивості, на відміну від `Object.keys`. - **Використовувати `target[prop]` усередині пастки `get`.** Це ламає успадкування і робить проксі непрозорим для класів з геттерами. - **Думати, що `Reflect` замінює `Object`.** Частина методів `Object` (наприклад `Object.keys`, `Object.assign`) не має аналогів у `Reflect`, це різні за призначенням набори.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.