Об'єкт Reflect
Reflect це вбудований об'єкт, який містить набір допоміжних методів для роботи з об'єктами: доступ до властивостей, їх видалення, створення, виклик функцій і таке інше. Простіше кажучи, Reflect це набір «безпечних» аналогів операторів JavaScript (in, delete, [], Object.defineProperty() і подібних), зібраний в одному місці.
Теорія
TL;DR
Reflectце вбудований об'єкт, не функція і не конструктор:new Reflect()неможливий.- Він дає єдиний інтерфейс до низькорівневих операцій над об'єктами.
- Його методи повертають
trueабоfalseзамість того, щоб кидати помилку, коли операція неможлива. - Кожній пастці
Proxyвідповідає однойменний методReflectз такою самою сигнатурою. - Усередині пасток
Reflectгарантує коректну передачуthisчерез аргументreceiver.
Швидкий приклад
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
- Єдиний інтерфейс для низькорівневих операцій над об'єктами, замість різних операторів і функцій (
delete,in,Object.definePropertyі так далі). - Робота в парі з
Proxy, щоб можна було делегувати дії назад на оригінальний об'єкт. - Передбачуваніша поведінка: методи повертають
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).
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, це різні за призначенням набори.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.