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 los Reflect
métodos del -objeto y solo establece lo siguiente sobre el Reflect
-objeto en sí:
El objeto Reflect es un solo objeto ordinario.
El valor de la ranura interna [[Prototype]] del objeto Reflect es el objeto prototipo de objeto integrado estándar (19.1.3).
El objeto Reflect no es un objeto de función. No tiene un método interno [[Construct]]; no es posible utilizar el objeto Reflect como constructor con el operador new . El objeto Reflect tampoco tiene un método interno [[Call]]; no es posible invocar el objeto Reflect como función.
Sin embargo, hay una breve explicación sobre su propósito en ES Harmony :
El módulo "@reflect" tiene múltiples propósitos:
- Ahora que tenemos módulos, un módulo “@reflect” es un lugar más natural para muchos de los métodos de reflexión previamente definidos en Object. Por motivos de compatibilidad con versiones anteriores, es poco probable que desaparezcan los métodos estáticos de Object. Sin embargo, es probable que se agreguen nuevos métodos al módulo “@reflect” en lugar de al constructor de objetos.
- Un hogar natural para los proxies, evitando la necesidad de un enlace Proxy global.
- La mayoría de los métodos de este módulo se asignan uno a uno a las trampas de proxy. Los controladores de proxy necesitan estos métodos para reenviar operaciones de manera conveniente, como se muestra a continuación.
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 en Object
, como Reflect.getOwnPropertyDescriptor
y Reflect.defineProperty
. Sin embargo, mientras Object.defineProperty(obj, name, desc)
que retornará obj
cuando la propiedad se definió con éxito, o arrojará un valor diferente TypeError
, 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);
} catch (e) {
}
A esto:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
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) y Reflect.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 usa delete 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)
y Reflect.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 matriz args
y enlazando el this
valor obj
, se puede escribir:
f.apply(obj, args)
Sin embargo, f
podría ser un objeto que, de forma intencionada o no, defina su propio apply
método. Cuando realmente quiere asegurarse de que apply
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
o F.call
llamar a una función con un número variable de argumentos, pero no hay F.construct
función para new
la función con un número variable de argumentos. Con Reflect
, 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 objeto obj
:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
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 las Proxy
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 = ...
obj[name]
obj[name] = value
Los métodos Reflect.get
y le Reflect.set
permiten hacer lo mismo, pero además aceptan como último argumento opcional un receiver
parámetro que le permite establecer explícitamente el this
-binding cuando la propiedad que obtiene / establece es un descriptor de acceso:
var name = ...
Reflect.get(obj, name, 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, si obj
se define como:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
Llamar Reflect.get(obj, "foo", wrapper)
hará que la this.bar()
llamada se desvíe a wrapper
.
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étodo Object.getPrototypeOf(obj)
para consultar el prototipo. Reflect.getPrototypeOf(obj)
hace exactamente lo mismo, excepto que Reflect
también define un correspondiente Reflect.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
y Loader
objetos.
Este enlace ofrece otra explicación :
Un objeto de reino abstrae la noción de un entorno global distinto, con su propio objeto global, copia de la biblioteca estándar e "intrínsecos" (objetos estándar que no están vinculados a variables globales, como el valor inicial de Object.prototype).
Web extensible : este es el equivalente dinámico de un mismo origen
<iframe>
sin DOM.
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!
Reflect
es solo un contenedor para objetosRealm
yLoader
, pero tampoco sé qué hacen estos últimos.