Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить Reflect?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`Reflect`** - це вбудований об'єкт (як `Math` чи `JSON`), що містить статичні методи для роботи з об'єктами та функціями на низькому рівні. **Ключове:** це уніфікований API для базових операцій над об'єктами (читання, запис, виклик, створення), методи якого відповідають тим самим операціям, які можна перехоплювати через `Proxy`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке `Reflect` `Reflect` - це **вбудований об'єкт** (як `Math` або `JSON`), який містить **статичні методи** для роботи з об'єктами і функціями на низькому рівні. Простіше кажучи: > `Reflect` - це "уніфікований API" для базових операцій над об'єктами: читання, запис, виклик, створення тощо. > Його методи відповідають тим самим операціям, які можна перехоплювати через `Proxy`. ## Навіщо він потрібен Раніше (до ES6) операції на кшталт `delete obj.prop` або `obj[prop] = value` виконувалися "вбудованим синтаксисом", але **не мали функціонального аналога**. `Reflect` з'явився, щоб: 1. Зробити ці операції доступними як **функції**; 2. Спростити написання пасток `Proxy` (можна делегувати виконання через `Reflect`); 3. Зробити API симетричним і безпечним. ## Приклад 1 - безпечне читання і запис властивостей ```javascript const user = { name: "Tim" }; console.log(Reflect.get(user, "name")); // "Tim" Reflect.set(user, "age", 30); console.log(user.age); // 30 ``` Аналог: ```javascript user.name; // get user.age = 30; // set ``` Але з `Reflect` ти можеш використовувати це **функціонально**, передаючи `target`, `key`, `receiver` вручну. ## Приклад 2 - видалення властивості ```javascript const user = { name: "Tim" }; delete user.name; // традиційний синтаксис // Еквівалент через Reflect: Reflect.deleteProperty(user, "name"); ``` Відмінність: `Reflect.deleteProperty` **повертає true/false**, а не кидає виняток, якщо властивість "configurable: false". ## Приклад 3 - створення властивості з флагами ```javascript const user = {}; Reflect.defineProperty(user, "role", { value: "admin", writable: false }); console.log(user.role); // admin ``` (це функціональний аналог `Object.defineProperty`) ## Приклад 4 - перевірка наявності властивості ```javascript const user = { name: "Tim" }; console.log("name" in user); // true console.log(Reflect.has(user, "name")); // true ``` ## Приклад 5 - отримання ключів ```javascript const user = { a: 1, b: 2 }; console.log(Reflect.ownKeys(user)); // ['a', 'b'] ``` На відміну від `Object.keys()`, повертає **всі** ключі, включно з `Symbol`. ## Приклад 6 - керування прототипом ```javascript const user = {}; const proto = { greet() { console.log("hi"); } }; Reflect.setPrototypeOf(user, proto); Reflect.getPrototypeOf(user).greet(); // "hi" ``` ## Приклад 7 - виклик функції ```javascript function sum(a, b) { return a + b; } console.log(Reflect.apply(sum, null, [2, 3])); // 5 ``` Це безпечний аналог `Function.prototype.apply.call(sum, ...)` ## Приклад 8 - створення екземплярів ```javascript class User { constructor(name) { this.name = name; } } const user = Reflect.construct(User, ["Tim"]); console.log(user.name); // "Tim" ``` ## Список усіх методів `Reflect` | Метод | Що робить | |---|---| | **Reflect.apply(target, thisArg, args)** | Викликає функцію з указаним `this` і аргументами | | **Reflect.construct(target, args)** | Аналог `new target(...args)` | | **Reflect.defineProperty(target, key, descriptor)** | Створює/змінює властивість | | **Reflect.deleteProperty(target, key)** | Видаляє властивість (аналог `delete`) | | **Reflect.get(target, key, receiver?)** | Повертає значення властивості | | **Reflect.set(target, key, value, receiver?)** | Встановлює значення властивості | | **Reflect.has(target, key)** | Перевіряє наявність властивості (`in`) | | **Reflect.ownKeys(target)** | Повертає всі ключі (включно з `Symbol`) | | **Reflect.getOwnPropertyDescriptor(target, key)** | Повертає дескриптор властивості | | **Reflect.preventExtensions(target)** | Забороняє додавати нові властивості | | **Reflect.isExtensible(target)** | Перевіряє, чи можна додавати властивості | | **Reflect.getPrototypeOf(target)** | Отримує прототип | | **Reflect.setPrototypeOf(target, proto)** | Встановлює прототип | ## Приклад 9 - Reflect + Proxy (класична зв'язка) ```javascript const user = { name: "Tim", age: 25 }; const proxy = new Proxy(user, { get(target, prop, receiver) { console.log(`Читання властивості: ${prop}`); return Reflect.get(target, prop, receiver); // безпечно делегуємо }, set(target, prop, value, receiver) { console.log(`Зміна властивості: ${prop}`); return Reflect.set(target, prop, value, receiver); } }); proxy.name; // Читання властивості: name proxy.age = 30; // Зміна властивості: age ``` Використання `Reflect` всередині пасток гарантує, що поведінка буде коректною, навіть якщо об'єкт має геттери, сеттери або прототип. ## Відмінність `Reflect` від `Object` | Особливість | `Object` | `Reflect` | |---|---|---| | Орієнтація | Методи для роботи зі структурою об'єктів | Універсальні низькорівневі операції | | Повернення помилок | Методи можуть кидати винятки | Методи частіше повертають `false` | | Функціональність | Не можна викликати оператори як функції | Можна (наприклад, `Reflect.deleteProperty` замість `delete`) | | Зв'язок з Proxy | Немає | Методи 1-в-1 відповідають пасткам Proxy | ## Підсумок | Що робить | Приклад | |---|---| | Читає властивість | `Reflect.get(obj, "x")` | | Пише властивість | `Reflect.set(obj, "x", 10)` | | Перевіряє наявність | `Reflect.has(obj, "x")` | | Видаляє властивість | `Reflect.deleteProperty(obj, "x")` | | Отримує ключі | `Reflect.ownKeys(obj)` | | Викликає функцію | `Reflect.apply(fn, thisArg, args)` | | Створює об'єкт | `Reflect.construct(Class, args)` | | Працює з прототипом | `Reflect.getPrototypeOf(obj)` / `Reflect.setPrototypeOf(obj, proto)` | **Головна ідея:** > `Reflect` - це "дзеркало" базових операцій JavaScript у вигляді функцій. > Він робить код чистішим, безпечнішим і передбачуванішим, особливо під час роботи з `Proxy`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.