Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Чим Reflect відрізняється від Object?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`Reflect`** і **`Object`** обидва працюють із властивостями об'єктів, але створені для різних цілей: різниця між ними - у філософії, поведінці та застосуванні. **Ключове:** при помилці `Object` кидає виняток, а `Reflect` повертає `false` - це робить `Reflect` "тихим" і передбачуваним варіантом `Object`-методів.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення`Reflect` і `Object` дійсно схожі (обидва працюють із властивостями об'єктів), але вони **створені для різних цілей**. Різниця між ними - у **філософії, поведінці та застосуванні**. Розберемо по кроках: --- ## Коротка відповідь | Критерій | `Object` | `Reflect` | |---|---|---| | Основне призначення | Робота з об'єктами (створення, прототипи, властивості) | Метапрограмування - "керування поведінкою" об'єктів | | Виник | З самого початку JS | У ES6 (ES2015) | | Поведінка при помилках | Кидає винятки | Повертає `true` / `false` | | Використовується в | звичайному коді | Proxy, безпечних викликах, внутрішніх операціях | | Тип результату | Різний (об'єкт, значення тощо) | Майже завжди булеве значення або примітив | | Статус | "старе" API | "сучасне, відображальне" API | --- ## Приклад - defineProperty ### Object: ```javascript try { Object.defineProperty({}, 'x', { value: 1, writable: false }); console.log('ok'); } catch { console.log('Помилка!'); } ``` Якщо операція не вдалася (наприклад, об'єкт заморожений) - буде кинуто **помилку**. --- ### Reflect: ```javascript const obj = Object.freeze({}); const result = Reflect.defineProperty(obj, 'x', { value: 1 }); console.log(result); // false (без помилки) ``` `Reflect.defineProperty()` просто поверне `false`, а не перерве виконання програми. --- ## Приклад - видалення властивості ### Через delete ```javascript const user = { name: 'Tim' }; delete user.name; // true ``` ### Через Reflect (безпечніше) ```javascript const user = { name: 'Tim' }; console.log(Reflect.deleteProperty(user, 'name')); // true console.log(Reflect.deleteProperty(Object.freeze({x: 4}), 'x')); // false ``` `Reflect.deleteProperty()` робить те саме, але **не кидає помилок** і повертає **логічний результат**. --- ## Приклад - виклик функції ```javascript function greet(msg) { console.log(msg, this.name); } const user = { name: 'Tim' }; Reflect.apply(greet, user, ['Привіт']); // "Привіт Tim" ``` `Reflect.apply()` - аналог `Function.prototype.apply()`, але більш явний і зручний для Proxy-пасток і метапрограмування. --- ## Приклад - створення об'єкта ```javascript class User { constructor(name) { this.name = name; } } const tim = Reflect.construct(User, ['Tim']); console.log(tim.name); // "Tim" ``` `Reflect.construct()` - "відображальна" версія `new`, корисна, якщо потрібно динамічно створити екземпляр класу. --- ## Приклад - перевірка властивості ```javascript const user = { name: 'Tim' }; console.log('name' in user); // true console.log(Reflect.has(user, 'name')); // true ``` `Reflect.has()` - це те саме, що оператор `in`, але як функція (зручно при динамічних викликах). --- ## Приклад - отримання і встановлення властивості ```javascript const user = { name: 'Tim' }; Reflect.set(user, 'name', 'Oleh'); console.log(Reflect.get(user, 'name')); // "Oleh" ``` Аналог `user.name = ...` та `user.name`, але у "функціональній" формі (зручно використовувати в Proxy). --- ## Поведінка при помилках | Метод | `Object` | `Reflect` | |---|---|---| | `Object.defineProperty(frozen, 'x', {...})` | кидає помилку | повертає `false` | | `Object.getPrototypeOf(null)` | TypeError | повертає `false` | | `Object.setPrototypeOf(sealed, ...)` | кидає помилку | повертає `false` | Тобто `Reflect` - "тихий" і передбачуваний варіант `Object`-методів. --- ## Методи, яких немає в Object | Метод Reflect | Що робить | Аналог | |---|---|---| | `Reflect.apply()` | Викликає функцію із зазначеним `this` і аргументами | `func.apply()` | | `Reflect.construct()` | Аналог оператора `new` | - | | `Reflect.get()` / `Reflect.set()` | Отримує / задає значення властивості | `obj[key]` | | `Reflect.has()` | Перевіряє наявність властивості | `'key' in obj` | | `Reflect.deleteProperty()` | Видаляє властивість | `delete obj.key` | | `Reflect.ownKeys()` | Повертає всі ключі (включно з `Symbol`) | `Object.getOwnPropertyNames()` + `Object.getOwnPropertySymbols()` | --- ## Приклад реального застосування - Proxy `Reflect` ідеально працює в парі з `Proxy`, щоб типово пробрасувати стандартну поведінку. ```javascript const user = { name: 'Tim' }; const proxy = new Proxy(user, { get(target, key) { console.log(`Читання ${key}`); return Reflect.get(target, key); // безпечно делегуємо } }); console.log(proxy.name); // Вивід: // Читання name // "Tim" ``` Без `Reflect.get()` довелося б вручну писати `target[key]`, а це може спричинити помилки у складніших випадках (аксесори, прототипи тощо). --- ## Підсумок | Критерій | `Object` | `Reflect` | |---|---|---| | Мета | Робота з властивостями і прототипами | Метапрограмування, "відображення" поведінки | | Виник | З самого початку JS | ES6 (2015) | | При помилці | Кидає виняток | Повертає `false` | | Значення, що повертається | Різне | Передбачуване | | Підтримка Proxy | Немає | Так | | Зручність у функціональних викликах | Середня | Висока |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.