Skip to main content

Об'єкт Reflect

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)Повертає всі ключі, включно з SymbolObject.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, це різні за призначенням набори.

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

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

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