Vi un código auxiliar en blanco en MDN hace un tiempo para el Reflect
objeto en javascript, pero no puedo por mi vida encontrar nada en Google. Hoy encontré este http://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect-object y suena similar al objeto Proxy, aparte de la funcionalidad de reino y cargador.
Básicamente, no sé si esta página que encontré solo explica cómo implementar Reflect o si simplemente no puedo entender su redacción. ¿Podría alguien explicarme en general cuáles son los métodos Reflect
?
Por ejemplo, en la página que encontré dice que la llamada Reflect.apply ( target, thisArgument, argumentsList )
"Devolverá el resultado de llamar al método interno [[Call]] del objetivo con argumentos thisArgument y args". pero, ¿en qué se diferencia eso de simplemente llamar target.apply(thisArgument, argumentsList)
?
Actualizar:
Gracias a @Blue, encontré esta página en la wiki http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect
que, a mi leal saber y entender, dice que el objeto reflect
proporciona versiones de métodos de todos las acciones que pueden ser atrapadas por los proxies para facilitar el reenvío. Pero eso me parece un poco extraño ya que no veo cómo es del todo necesario. Pero parece hacer un poco más que eso, particularmente el par que dice double-lifting
pero que apunta a la antigua especificación de proxy /
fuente
Reflect
es solo un contenedor para objetosRealm
yLoader
, pero tampoco sé qué hacen estos últimos.Reflect.Loader
yReflect.Realm
tener algo que ver con la sobrecarga de la funcionalidad del módulo?isExtensible
,ownKeys
etc. ES 6, con clases reales, esto es útil para saber más acerca de una clase (target
en 16.1.2 creo).Respuestas:
ACTUALIZACIÓN 2015: Como se señaló en la respuesta de 7th , ahora que ES6 (ECMAScript 2015) se ha finalizado, ahora se encuentra disponible documentación más apropiada:
Respuesta original (para comprensión (histórica) y ejemplos adicionales) :
El
Reflection proposal
parece haber progresado hasta el Proyecto de ECMAScript 6 Especificación . Este documento actualmente describe losReflect
métodos del -objeto y solo establece lo siguiente sobre elReflect
-objeto en sí:Sin embargo, hay una breve explicación sobre su propósito en ES Harmony :
Por lo tanto, el
Reflect
objeto proporciona una serie de funciones de utilidad, muchas de las cuales parecen superponerse con los métodos de ES5 definidos en el objeto global.Sin embargo, eso realmente no explica qué problemas existentes pretende resolver o qué funcionalidad se agrega. Sospeché que esto podría ser alterado y, de hecho, la especificación de armonía anterior se vincula a una `` implementación aproximada no normativa de estos métodos '' .
Examinar ese código podría dar (más) ideas sobre su uso, pero afortunadamente también hay una wiki que describe una serie de razones por las que el objeto Reflect es útil :
(He copiado (y formateado) el siguiente texto para referencia futura de ese fuente ya que son los únicos ejemplos que pude encontrar. Además de eso, tienen sentido, ya tienen una buena explicación y tocan el
apply
ejemplo de la pregunta .)Valores de retorno más útiles
Muchas operaciones en
Reflect
son similares a las operaciones de ES5 definidas enObject
, comoReflect.getOwnPropertyDescriptor
yReflect.defineProperty
. Sin embargo, mientrasObject.defineProperty(obj, name, desc)
que retornaráobj
cuando la propiedad se definió con éxito, o arrojará un valor diferenteTypeError
,Reflect.defineProperty(obj, name, desc)
se especifica para devolver simplemente un valor booleano que indique si la propiedad se definió correctamente o no. Esto le permite refactorizar este código:try { Object.defineProperty(obj, name, desc); // property defined successfully } catch (e) { // possible failure (and might accidentally catch the wrong exception) }
A esto:
if (Reflect.defineProperty(obj, name, desc)) { // success } else { // failure }
Otros métodos que devuelven un estado de éxito booleano son
Reflect.set
(actualizar una propiedad),Reflect.deleteProperty
(eliminar una propiedad),Reflect.preventExtensions
(hacer que un objeto no sea extensible) yReflect.setPrototypeOf
(actualizar el enlace del prototipo de un objeto).Operaciones de primera
En ES5, la forma de detectar si un objeto
obj
define o hereda un determinado nombre de propiedad es escribir(name in obj)
. De manera similar, para eliminar una propiedad, se usadelete obj[name]
. Si bien la sintaxis dedicada es agradable y breve, también significa que debe envolver explícitamente estas operaciones en funciones cuando desee pasar la operación como un valor de primera clase.Con
Reflect
, estas operaciones se definen fácilmente como funciones de primera clase:Reflect.has(obj, name)
es el equivalente funcional de(name in obj)
yReflect.deleteProperty(obj, name)
es una función que hace lo mismo quedelete obj[name].
Aplicación de funciones más confiable
En ES5, cuando uno quiere llamar a una función
f
con un número variable de argumentos empaquetados como una matrizargs
y enlazando elthis
valorobj
, se puede escribir:Sin embargo,
f
podría ser un objeto que, de forma intencionada o no, defina su propioapply
método. Cuando realmente quiere asegurarse de queapply
se llama a la función incorporada , normalmente se escribe:Function.prototype.apply.call(f, obj, args)
Esto no solo es detallado, sino que rápidamente se vuelve difícil de entender. Con
Reflect
, ahora puede realizar una llamada de función confiable de una manera más corta y más fácil de entender:Reflect.apply(f, obj, args)
Constructores de argumentos variables
Imagina que quieres llamar a una función constructora con un número variable de argumentos. En ES6, gracias a la nueva sintaxis de propagación, será posible escribir código como:
var obj = new F(...args)
En ES5, esto es más difícil de escribir, porque solo se puede usar
F.apply
oF.call
llamar a una función con un número variable de argumentos, pero no hayF.construct
función paranew
la función con un número variable de argumentos. ConReflect
, ahora se puede escribir, en ES5:var obj = Reflect.construct(F, args)
Comportamiento de reenvío predeterminado para capturas de proxy
Cuando se utilizan
Proxy
objetos para envolver objetos existentes, es muy común interceptar una operación, hacer algo y luego "hacer lo predeterminado", que normalmente es aplicar la operación interceptada al objeto envuelto. Por ejemplo, digamos que simplemente quiero registrar todos los accesos de propiedad a un objetoobj
:var loggedObj = new Proxy(obj, { get: function(target, name) { console.log("get", target, name); // now do the default thing } });
Las API
Reflect
y se diseñaron en conjunto , de modo que para cada trampa, existe un método correspondiente que "hace lo predeterminado". Por lo tanto, cada vez que desee "hacer lo predeterminado" dentro de un controlador Proxy, lo correcto es llamar siempre al método correspondiente en el objeto:Proxy
Proxy
Reflect
Reflect
var loggedObj = new Proxy(obj, { get: function(target, name) { console.log("get", target, name); return Reflect.get(target, name); } });
Se
Reflect
garantiza que el tipo de retorno de los métodos es compatible con el tipo de retorno de lasProxy
trampas.Controlar la vinculación de los accesos
En ES5, es bastante fácil realizar un acceso de propiedad genérico o una actualización de propiedad. Por ejemplo:
var name = ... // get property name as a string obj[name] // generic property lookup obj[name] = value // generic property update
Los métodos
Reflect.get
y leReflect.set
permiten hacer lo mismo, pero además aceptan como último argumento opcional unreceiver
parámetro que le permite establecer explícitamente elthis
-binding cuando la propiedad que obtiene / establece es un descriptor de acceso: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)
En ocasiones, esto es útil cuando está ajustando
obj
y desea que cualquier autoenvío dentro del descriptor de acceso sea redirigido a su envoltorio, por ejemplo, siobj
se define como:var obj = { get foo() { return this.bar(); }, bar: function() { ... } }
Llamar
Reflect.get(obj, "foo", wrapper)
hará que lathis.bar()
llamada se desvíe awrapper
.Evita el legado
__proto__
En algunos navegadores,
__proto__
se define como una propiedad especial que da acceso al prototipo de un objeto. ES5 estandarizó un nuevo métodoObject.getPrototypeOf(obj)
para consultar el prototipo.Reflect.getPrototypeOf(obj)
hace exactamente lo mismo, excepto queReflect
también define un correspondienteReflect.setPrototypeOf(obj, newProto)
para configurar el prototipo del objeto. Esta es la nueva forma compatible con ES6 de actualizar el prototipo de un objeto.Tenga en cuenta que:
setPrototypeOf
también existe enObject
(como se indica correctamente en el comentario de Knu ).EDITAR:
Nota al margen (dirigiendo comentarios a la Q): Hay una respuesta corta y simple en 'Q: Módulos ES6 vs. Importaciones HTML' que explica
Realms
yLoader
objetos.Este enlace ofrece otra explicación :
Sin embargo, vale la pena mencionarlo:
todo esto aún está en borrador, ¡esta no es una especificación grabada en piedra!Es ES6, ¡así que tenga en cuenta la compatibilidad del navegador!¡Espero que esto ayude!
fuente
Reflect.apply
ytarget.apply
? ¿O qué debo agregar antes de que termine la recompensa?Object
.Reflect.get
como implementación predeterminada para proxy get no funciona bien si está usando un objeto con propiedades de prototipo. Simplemente se queja de que no funciona. Sin embargo, si usaReflect.get(target, property)
sin pasar elreceiver
, entonces funciona.target
es el objetivo original que envuelve el proxy, mientras quereceiver
es el propio proxy. Pero nuevamente, esto podría ser diferente si logra acceder a las propiedades de manera diferente.Siguiendo el borrador del documento que se encuentra en la wiki,
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
Obtenemos la línea sobre "objeto ordinario único" que aclara en el borrador. También tiene las definiciones de funciones.
La wiki debe ser confiable, ya que puede encontrar un enlace desde el sitio web de emcascript.
http://www.ecmascript.org/dev.php
Sin embargo, encontré el primer enlace de Google y no tuve suerte para encontrarlo buscando directamente en la wiki.
fuente