Некоторое время назад я видел пустую заглушку на MDN для Reflect
объекта в javascript, но я не могу найти что-либо в Google. Сегодня я нашел этот http://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect-object, и он похож на объект Proxy, за исключением функциональности области и загрузчика.
По сути, я не знаю, объясняет ли эта страница, которую я нашел, только то, как реализовать Reflect, или я просто не могу понять ее формулировку. Может ли кто-нибудь объяснить мне в целом, что Reflect
делают методы ?
Например, на найденной мной странице сказано, что при вызове Reflect.apply ( target, thisArgument, argumentsList )
будет «возвращен результат вызова внутреннего метода [[Call]] цели с аргументами thisArgument и args». но чем это отличается от простого звонка target.apply(thisArgument, argumentsList)
?
Обновить:
Благодаря @Blue я нашел эту страницу в вики
http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect,
которая, насколько мне известно, говорит, что объект отражения предоставляет версии методов всех действия, которые могут быть перехвачены прокси, чтобы упростить пересылку. Но мне это кажется немного странным, поскольку я не понимаю, насколько это необходимо. Но, похоже, он делает немного больше, особенно параграф, который говорит, double-lifting
но указывает на старую спецификацию прокси /
источник
Reflect
это просто контейнер дляRealm
иLoader
объектов, но я не знаю , что последнее сделать что- либо.Reflect.Loader
иReflect.Realm
есть что - то с перегрузкой функциональности модуля?isExtensible
иownKeys
т. Д. В ES 6 с реальными классами это полезно, чтобы узнать больше о классе ( я думаю,target
в 16.1.2 ).Ответы:
ОБНОВЛЕНИЕ 2015: Как указано в ответе 7 -го , теперь, когда ES6 (ECMAScript 2015) был завершен, теперь доступна более подходящая документация:
Оригинальный ответ (для (исторического) понимания и дополнительных примеров) :
Reflection proposal
, Кажется, продвинулись к проекту ECMAScript 6 Спецификация . В этом документе в настоящее времяReflect
описываются методы -object и говорится только о самомReflect
-object:Тем не менее, есть краткое объяснение его цели в ES Harmony :
Итак
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); // property defined successfully } catch (e) { // possible failure (and might accidentally catch the wrong exception) }
К этому:
if (Reflect.defineProperty(obj, name, desc)) { // success } else { // failure }
Другие методы, которые возвращают такой логический статус успеха:
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
метод. Когда вы действительно хотите убедиться, что встроенная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); // now do the default thing } });
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 = ... // get property name as a string obj[name] // generic property lookup obj[name] = value // generic property update
В
Reflect.get
иReflect.set
методы позволяют делать то же самое, но дополнительно принимают в качестве последнего необязательного аргумента вreceiver
параметр , который позволяет явно установитьthis
-связывающего когда свойство , что вы получите / набор аксессор:var name = ... // get property name as a string Reflect.get(obj, name, wrapper) // if obj[name] is an accessor, it gets run with `this === 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
объекты.Другое объяснение предлагается по этой ссылке :
Однако стоит упомянуть:
все это еще в черновике, это не спецификация, выгравированная на камне!Это ES6, так что помните о совместимости с браузером!Надеюсь это поможет!
источник
Reflect.apply
иtarget.apply
? Или что мне добавить до окончания награды?Object
.Reflect.get
в качестве реализации по умолчанию для прокси get не очень хорошо работает, если вы проксируете объект со свойствами прототипа. Он просто жалуется, что не работает. Однако, если вы вместо этого используете,Reflect.get(target, property)
не передаваяreceiver
, тогда он действительно работает.target
это исходная цель, которую оборачивает прокси, аreceiver
сам прокси. Но опять же, это может быть иначе, если вам удастся получить доступ к свойствам по-другому.Следуя черновику документа, найденному в вики,
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
Получается строчка про «единичный обычный объект», проясняемая в черновике. В нем также есть определения функций.
Вики должна быть надежной, поскольку вы можете найти ссылку на нее на сайте emcascript.
http://www.ecmascript.org/dev.php
Я нашел первую ссылку от Google, но мне не удалось найти ее, напрямую выполнив поиск в вики.
источник