Обзор
Proxy и Reflect — это API, представленные в ES6 для работы с объектами.
Proxy может перехватывать операции над целевым объектом, такие как чтение и вызовы функций, а затем выполнять обработку операций. Он не работает с объектом напрямую, но, как и в паттерне «прокси», действует через прокси-объект этого объекта, и во время этих операций можно добавлять дополнительные необходимые операции.
Reflect можно использовать для получения поведения целевого объекта. Он похож на Object, но более читаемый, предоставляя более элегантный способ работы с объектами. Его методы соответствуют Proxy.
Базовое использование
Proxy
Объект Proxy состоит из двух частей: target и handler. При создании объекта-экземпляра через конструктор Proxy необходимо предоставить эти два параметра. target — это целевой объект, а handler — объект, который объявляет заданное поведение для проксирования target.
Методы экземпляра
get(target, propKey, receiver)
Используется для операции чтения propKey на целевом объекте.
Метод get() может наследоваться.
set(target, propKey, value, receiver)
Используется для перехвата операции присваивания propKey целевому объекту. Если свойство самого целевого объекта недоступно для записи и неконфигурируемо, то метод set не будет иметь эффекта.
Четвертый параметр receiver представляет объект, в котором находится исходное поведение операции, обычно сам экземпляр Proxy.
Примечание: в строгом режиме, если set proxy не возвращает true, будет выдана ошибка.
apply(target, ctx, args)
Используется для перехвата вызовов функций, операций call и reply. target представляет целевой объект, ctx представляет контекст целевого объекта, а args представляет массив аргументов целевого объекта.
has(target, propKey)
Используется для перехвата операции HasProperty, то есть, когда определяется, имеет ли целевой объект свойство propKey, это будет перехвачено этим методом. Этот метод не определяет, является ли свойство собственным свойством объекта или унаследованным свойством.
Примечание: этот метод не перехватывает циклы for...in.
construct(target, args)
Используется для перехвата команды new. Возвращаемое значение должно быть объектом.
deleteProperty(target, propKey)
Используется для перехвата операции delete. Если этот метод выбрасывает ошибку или возвращает false, свойство propKey не может быть удалено командой delete.
defineProperty(target, propKey, propDesc)
Используется для перехвата Object.definePro. Если целевой объект нерасширяемый, добавление свойства, которого нет в целевом объекте, приведёт к ошибке; если свойство недоступно для записи или ненастраиваемое, эти свойства нельзя изменить.
операция свойства
getOwnPropertyDescriptor(target, propKey)
Используется для перехвата Object.getOwnPropertyD(). Возвращаемое значение — объект дескриптора свойства или undefined.
ptor свойство
getPrototypeOf(target)
В основном используется для перехвата операций, получающих прототип объекта. Включает следующие операции:
- Object.prototype._proto_ - Object.prototype.isPrototypeOf() - Object.getPrototypeOf() - Reflect.getPrototypeOf() - instanceof
Примечание: возвращаемое значение должно быть объектом или null, иначе будет сообщено об ошибке. Кроме того, если объект target является нерасширяемым, метод getPrototypeOf должен возвращать объект-прототип объекта target.
isExtensible(target)
Используется для перехвата операции Object.isExtensible.
Этот метод может возвращать только логическое значение; в противном случае возвращаемое значение будет автоматически преобразовано в логическое.
Примечание: его возвращаемое значение должно соответствовать свойству isExtensible целевого объекта, иначе будет выброшена ошибка.
ownKeys(target)
Используется для перехвата операции чтения собственных свойств объекта. В основном включает следующие операции:
- Object.getOwnPropertyNames() - Object.getOwnPropertySymbols() - Object.keys() - or...in
Элементы массива, возвращаемые методом, могут быть только строками или значениями Symbol, иначе будет сообщено об ошибке.
Если целевой объект содержит неконфигурируемые свойства, эти свойства должны быть возвращены в результате, иначе будет сообщено об ошибке.
Если целевой объект является нерасширяемым, он должен вернуть все свойства, содержащиеся в целевом объекте, и только их; он не может включать несуществующие свойства, иначе также будет сообщено об ошибке.
preventExtensions(target)
Перехватывает операцию Object.preventExtensions.
Этот метод должен возвращать логическое значение, иначе оно будет автоматически преобразовано в логическое.
setPrototypeOf
В основном используется для перехвата метода Object.setPrototypeOf.
Возвращаемое значение должно быть логическим, иначе оно будет автоматически преобразовано в логическое.
Если целевой объект нерасширяемый, метод setPrototypeOf не должен изменять прототип целевого объекта.
Proxy.revocable()
Используется для возврата отзываемого экземпляра Proxy.
Reflect
В ES6 некоторые методы Object, которые явно относятся к внутренним механизмам языка, были перемещены в объект Reflect (в настоящее время некоторые методы существуют как в объекте Object, так и в объекте Reflect), а будущие новые методы будут добавлены только в объект Reflect.
Объект Reflect изменил возвращаемые результаты некоторых методов, чтобы сделать их более разумными.
Объект Reflect использует функции для реализации императивных операций Object.
Статические методы
Reflect.get(target, name, receiver)
Находит и возвращает свойство name целевого объекта.
Reflect.set(target, name, value, receiver)
Установите свойство name объекта target в value. Возвращаемое значение — boolean; true означает успех, false — неудачу. Когда target — несуществующий объект, будет выдана ошибка.
Reflect.has(obj, name)
Это функциональная форма оператора name in obj, используемая для проверки, существует ли свойство name в объекте obj. Возвращаемое значение — boolean. Если obj не является объектом, будет вызвана ошибка TypeError.
Reflect.deleteProperty(obj, property)
Это функциональная форма delete obj[property], используемая для удаления свойства property объекта obj. Возвращаемое значение — boolean. Если obj не является объектом, будет вызвана ошибка TypeError.
Reflect.construct(obj, args)
Эквивалентно new target(...args).
Reflect.getPrototypeOf(obj)
Используется для чтения свойства _proto_ объекта obj. Когда obj не является объектом, он не преобразует obj в объект, как это делает Object, а вместо этого сообщает об ошибке.
Reflect.setPrototypeOf(obj, newProto)
Используется для установки прототипа целевого объекта.
Reflect.apply(func, thisArg, args)
Эквивалентно Function.prototype.apply.call(func, thisArg, args). func представляет целевую функцию; thisArg представляет объект this, привязанный к целевой функции; args представляет список аргументов, передаваемых при вызове целевой функции, который может быть массивом или массивоподобным объектом. Если целевую функцию невозможно вызвать, выбрасывается TypeError.
Reflect.defineProperty(target, propertyKey, attributes)
Используется для определения свойств целевого объекта. Если target не является объектом, выбрасывается ошибка.
Reflect.getOwnPropertyDescriptor(target, propertyKey)
Используется для получения объекта дескриптора свойства propertyKey целевого объекта. Если target не является объектом, выбрасывается ошибка, указывающая на недопустимый параметр; не-объект не преобразуется в объект.
Reflect.isExtensible(target)
Используется для определения, является ли целевой объект расширяемым. Возвращаемое значение — логическое. Если параметр target не является объектом, выбрасывается ошибка.
Reflect.preventExtensions(target)
Используется, чтобы сделать целевой объект нерасширяемым. Если параметр target не является объектом, выбрасывается ошибка.
Reflect.ownKeys(target)
Используется для возврата всех свойств целевого объекта; эквивалентно комбинации Object.getOwnPropertyNames и Object.getOwnPropertySymbols.
Совместное использование
Методы объекта Reflect взаимно однозначно соответствуют методам объекта Proxy. Поэтому методы объекта Proxy могут получать поведение по умолчанию, вызывая методы объекта Reflect, а затем выполнять дополнительные операции.
Расширенные варианты использования
Реализация паттерна Observer.