Чим Reflect відрізняється від Object?
Reflect і Object дійсно схожі (обидва працюють із властивостями об'єктів), але вони створені для різних цілей. Різниця між ними - у філософії, поведінці та застосуванні.
Розберемо по кроках:
Коротка відповідь
| Критерій | Object | Reflect |
|---|---|---|
| Основне призначення | Робота з об'єктами (створення, прототипи, властивості) | Метапрограмування - "керування поведінкою" об'єктів |
| Виник | З самого початку JS | У ES6 (ES2015) |
| Поведінка при помилках | Кидає винятки | Повертає true / false |
| Використовується в | звичайному коді | Proxy, безпечних викликах, внутрішніх операціях |
| Тип результату | Різний (об'єкт, значення тощо) | Майже завжди булеве значення або примітив |
| Статус | "старе" API | "сучасне, відображальне" API |
Приклад - defineProperty
Object:
try {
Object.defineProperty({}, 'x', { value: 1, writable: false });
console.log('ok');
} catch {
console.log('Помилка!');
}Якщо операція не вдалася (наприклад, об'єкт заморожений) - буде кинуто помилку.
Reflect:
const obj = Object.freeze({});
const result = Reflect.defineProperty(obj, 'x', { value: 1 });
console.log(result); // false (без помилки)Reflect.defineProperty() просто поверне false, а не перерве виконання програми.
Приклад - видалення властивості
Через delete
const user = { name: 'Tim' };
delete user.name; // trueЧерез Reflect (безпечніше)
const user = { name: 'Tim' };
console.log(Reflect.deleteProperty(user, 'name')); // true
console.log(Reflect.deleteProperty(Object.freeze({x: 4}), 'x')); // falseReflect.deleteProperty() робить те саме, але не кидає помилок і повертає логічний результат.
Приклад - виклик функції
function greet(msg) {
console.log(msg, this.name);
}
const user = { name: 'Tim' };
Reflect.apply(greet, user, ['Привіт']); // "Привіт Tim"Reflect.apply() - аналог Function.prototype.apply(), але більш явний і зручний для Proxy-пасток і метапрограмування.
Приклад - створення об'єкта
class User {
constructor(name) {
this.name = name;
}
}
const tim = Reflect.construct(User, ['Tim']);
console.log(tim.name); // "Tim"Reflect.construct() - "відображальна" версія new, корисна, якщо потрібно динамічно створити екземпляр класу.
Приклад - перевірка властивості
const user = { name: 'Tim' };
console.log('name' in user); // true
console.log(Reflect.has(user, 'name')); // trueReflect.has() - це те саме, що оператор in, але як функція (зручно при динамічних викликах).
Приклад - отримання і встановлення властивості
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, щоб типово пробрасувати стандартну поведінку.
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 | Немає | Так |
| Зручність у функціональних викликах | Середня | Висока |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.