ОБНОВЛЕНИЕ 2015:
Как указано в ответе 7 -го , теперь, когда ES6 (ECMAScript 2015) был завершен, теперь доступна более подходящая документация:
Оригинальный ответ (для (исторического) понимания и дополнительных примеров) :
Reflection proposal
, Кажется, продвинулись к проекту ECMAScript 6 Спецификация . В этом документе в настоящее время Reflect
описываются методы -object и говорится только о самом Reflect
-object:
Объект Reflect - это простой обычный объект.
Значение внутреннего слота [[Prototype]] объекта Reflect - это стандартный встроенный объект-прототип Object (19.1.3).
Объект Reflect не является функциональным объектом. У него нет внутреннего метода [[Construct]]; невозможно использовать объект Reflect в качестве конструктора с оператором new . У объекта Reflect также нет внутреннего метода [[Call]]; невозможно вызвать объект Reflect как функцию.
Тем не менее, есть краткое объяснение его цели в ES Harmony :
Модуль «@reflect» служит нескольким целям:
- Теперь, когда у нас есть модули, модуль «@reflect» является более естественным местом для многих методов отражения, ранее определенных в Object. В целях обеспечения обратной совместимости маловероятно, что статические методы в Object исчезнут. Однако новые методы, скорее всего, следует добавлять в модуль «@reflect», а не в конструктор объекта.
- Естественный дом для прокси, избавляющий от необходимости в глобальной привязке прокси.
- Большинство методов в этом модуле однозначно сопоставляют ловушки прокси. Обработчики прокси-сервера нуждаются в этих методах для удобной пересылки операций, как показано ниже.
Итак Reflect
объект предоставляет ряд служебных функций, многие из которых, по-видимому, перекрываются с методами ES5, определенными в глобальном объекте.
Однако это на самом деле не объясняет, какие существующие проблемы это намеревается решить или какие функции добавляются. Я подозревал, что это можно исправить, и действительно, приведенная выше спецификация гармонии связана с «ненормативной приблизительной реализацией этих методов» .
Изучение этого кода может дать (дальнейшее) представление о его использовании, но, к счастью, есть также вики, в которой изложен ряд причин, по которым объект Reflect полезен :
(Я скопировал (и отформатировал) следующий текст для использования в будущем. источник, так как это единственные примеры, которые я смог найти. Кроме того, они имеют смысл, уже имеют хорошее объяснение и касаются apply
примера вопроса .)
Более полезные возвращаемые значения
Многие операции в Reflect
похожи на операции ES5, определенные в Object
, например, Reflect.getOwnPropertyDescriptor
и Reflect.defineProperty
. Однако, в то время как Object.defineProperty(obj, name, desc)
будет либо возвращать, obj
когда свойство было успешно определено, либо генерировать в TypeError
противном случае, Reflect.defineProperty(obj, name, desc)
указывается, что просто возвращает логическое значение, которое указывает, было ли свойство успешно определено. Это позволяет вам реорганизовать этот код:
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
К этому:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
Другие методы, которые возвращают такой логический статус успеха: Reflect.set
(обновить свойство), Reflect.deleteProperty
(удалить свойство), Reflect.preventExtensions
(сделать объект нерасширяемым) и Reflect.setPrototypeOf
(обновить ссылку на прототип объекта).
Первоклассные операции
В ES5 способ определить, определяет ли объект obj
определенное имя свойства или наследует его, заключается в записи (name in obj)
. Аналогично, чтобы удалить свойство, используется delete obj[name]
. Хотя выделенный синтаксис красив и краток, это также означает, что вы должны явно заключить эти операции в функции, если вы хотите передать операцию как первоклассное значение.
С Reflect
, эти операции легко определить как функции первого класса:
Reflect.has(obj, name)
является функциональным эквивалентом (name in obj)
и Reflect.deleteProperty(obj, name)
является функцией, которая выполняет то же самое, что иdelete obj[name].
Более надежное функциональное приложение
В ES5, когда кто-то хочет вызвать функцию f
с переменным количеством аргументов, упакованных в виде массива args
и привязав this
значение к нему obj
, можно написать:
f.apply(obj, args)
Однако f
может быть объект, который намеренно или непреднамеренно определяет свой собственный apply
метод. Когда вы действительно хотите убедиться, что встроенная apply
функция вызывается, обычно пишут:
Function.prototype.apply.call(f, obj, args)
Это не только многословно, но и быстро становится трудным для понимания. Теперь Reflect
вы можете сделать надежный вызов функции более коротким и понятным способом:
Reflect.apply(f, obj, args)
Конструкторы с переменным аргументом
Представьте, что вы хотите вызвать функцию-конструктор с переменным количеством аргументов. В ES6, благодаря новому синтаксису распространения, можно будет писать такой код, как:
var obj = new F(...args)
В ES5 это сложнее написать, потому что можно использовать F.apply
или F.call
вызывать функцию только с переменным числом аргументов, но F.construct
для new
функции с переменным количеством аргументов нет функции . С Reflect
, один теперь можно написать, в ES5:
var obj = Reflect.construct(F, args)
Поведение пересылки по умолчанию для ловушек прокси
При использовании Proxy
объектов для обертывания существующих объектов очень часто выполняется перехват операции, выполнение чего-либо, а затем «выполнение действия по умолчанию», которое обычно заключается в применении перехваченной операции к обернутому объекту. Например, скажем, я хочу просто регистрировать все обращения к объекту по свойствам obj
:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
Reflect
И Proxy
API , были разработаны в тандеме , так что для каждой Proxy
ловушки, существует соответствующий метод на Reflect
том , что «делает вещь по умолчанию». Следовательно, всякий раз, когда вы обнаруживаете, что хотите "сделать стандартную" вещь внутри обработчика Proxy, правильнее всего будет всегда вызывать соответствующий метод в Reflect
объекте:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
Reflect
Гарантируется, что возвращаемый тип методов совместим с возвращаемым типом Proxy
ловушек.
Управление привязкой this для аксессоров
В ES5 довольно легко выполнить общий доступ к свойству или обновить свойство. Например:
var name = ...
obj[name]
obj[name] = value
В Reflect.get
и Reflect.set
методы позволяют делать то же самое, но дополнительно принимают в качестве последнего необязательного аргумента в receiver
параметр , который позволяет явно установить this
-связывающего когда свойство , что вы получите / набор аксессор:
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
Это иногда бывает полезно, когда вы обертываете obj
и хотите, чтобы любые самоотправки в аксессоре перенаправлялись в вашу оболочку, например, если obj
определено как:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
Вызов Reflect.get(obj, "foo", wrapper)
приведет this.bar()
к перенаправлению вызова на wrapper
.
Избегайте наследия __proto__
В некоторых браузерах __proto__
определяется как специальное свойство, предоставляющее доступ к прототипу объекта. ES5 стандартизировал новый метод Object.getPrototypeOf(obj)
запроса прототипа. Reflect.getPrototypeOf(obj)
делает то же самое, за исключением того, что Reflect
также определяет соответствующий Reflect.setPrototypeOf(obj, newProto)
прототип объекта. Это новый совместимый с ES6 способ обновления прототипа объекта.
Обратите внимание , что: setPrototypeOf
также существует наObject
(как правильно указал КНС «s комментарий )!
РЕДАКТИРОВАТЬ:
примечание (обращаясь к комментариям к Q): есть короткий и простой ответ на «Q: Модули ES6 против импорта HTML», который объясняет Realms
и Loader
объекты.
Другое объяснение предлагается по этой ссылке :
Объект области абстрагирует понятие отдельной глобальной среды со своим собственным глобальным объектом, копией стандартной библиотеки и «внутренними компонентами» (стандартные объекты, которые не привязаны к глобальным переменным, как начальное значение Object.prototype).
Расширяемый веб : это динамический эквивалент того же происхождения
<iframe>
без DOM.
Однако стоит упомянуть: все это еще в черновике, это не спецификация, выгравированная на камне! Это ES6, так что помните о совместимости с браузером!
Надеюсь это поможет!
Reflect
это просто контейнер дляRealm
иLoader
объектов, но я не знаю , что последнее сделать что- либо.