Подтвердить что ты не робот

Что делает объект Reflect в JavaScript?

Я видел пустой кусок на 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)?

Update:

Благодаря @Blue, я нашел эту страницу в вики http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect который, насколько мне известно, говорит, что объект отражения предоставляет версии методов всех действий, которые могут быть захвачены прокси-серверами, чтобы упростить пересылку. Но это кажется мне немного странным, так как я не вижу, как это абсолютно необходимо. Но это похоже на нечто большее, особенно на пар, который говорит double-lifting, но это указывает на старый прокси-spec/

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ 2015: Как отметил 7th ответ, теперь, когда ES6 (ECMAScript 2015) завершена, более уместно теперь доступна документация:


Оригинальный ответ (для (исторического) понимания и дополнительных примеров):

Кажется, что Reflection proposal перешел к проекту спецификации ECMAScript 6. В этом документе в настоящее время описываются методы Reflect -объектов и только указано следующее о Reflect -объекте:

Объект Reflect является единственным обычным объектом.

Значение внутреннего слота [[Prototype]] объекта Reflect является стандартным встроенным объектом прототипа объекта (19.1.3).

Объект Reflect не является объектом функции. У него нет внутреннего метода [[Construct]]; невозможно использовать объект Reflect в качестве конструктора с оператором new. Объект Reflect также не имеет внутреннего метода [[Call]]; невозможно вызвать объект Reflect как функцию.

Однако есть короткое объяснение этой цели в ES Harmony:

Модуль "@reflect" выполняет множество задач:
  • Теперь, когда у нас есть модули, модуль "@reflect" является более естественным местом для многих методов отражения, ранее определенных для Object. Для целей обратной совместимости маловероятно, что статические методы на объекте исчезнут. Однако новые методы, вероятно, должны быть добавлены к модулю "@reflect" , а не к конструктору Object.
  • Естественный дом для прокси, избегая необходимости глобального связывания прокси.
  • Большинство методов в этом модуле сопоставляются взаимно однозначно с прокси-ловушками. Прокси-обработчики нуждаются в этих методах для удобной пересылки операций, как показано ниже.



Таким образом, объект 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(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);
    // now do the default thing
  }
});

API-интерфейсы Reflect и Proxy были созданы в тандеме, так что для каждой ловушки 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.


Управление этим связыванием аксессуаров

В 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, когда свойство, которое вы get/set - это accessor:

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 (как правильно указано Knu comment)!


EDIT:
Боковая заметка (адресация комментариев к Q): есть короткий и простой ответ на тему "Q: ES6 Modules vs. HTML Imports" , в котором объясняются Realms и Loader объектов.

Другое объяснение предлагается эта ссылка:

Объект области абстрагирует понятие отдельной глобальной среды, с его собственным глобальным объектом, копией стандартной библиотеки и "intrinsics" (стандартные объекты, не привязанные к глобальным переменным, как начальное значение Object.prototype).

Расширяемая сеть: это динамический эквивалент одного и того же происхождения <iframe> без DOM.

Стоит упомянуть: все это все еще в черновике, это не спецификация, выгравированная в камне! Это ES6, поэтому учитывайте совместимость с браузером!

Надеюсь, это поможет!

Ответ 2

Переход по проекту документа, найденному в wiki,

http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts

Мы получаем строку о "единственном обычном объекте", который он разъясняет в черновике. Он также имеет определения функций.

Вики должна быть надежной, так как вы можете найти ссылку на нее с веб-сайта emcascript

http://www.ecmascript.org/dev.php

Я нашел первую ссылку google, хотя мне и не повезло найти ее, просто просмотрев wiki.