MISE À JOUR 2015:
Comme indiqué par la réponse de 7th , maintenant que ES6 (ECMAScript 2015) est finalisé, une documentation plus appropriée est désormais disponible:
Réponse originale (pour une compréhension (historique) et des exemples supplémentaires) :
Le Reflection proposal
semble avoir progressé vers le projet de spécification ECMAScript 6 . Ce document décrit actuellement les Reflect
méthodes de -object et indique uniquement ce qui suit sur Reflect
-object lui-même:
L'objet Reflect est un objet ordinaire unique.
La valeur de l'emplacement interne [[Prototype]] de l'objet Reflect est l'objet prototype Object intégré standard (19.1.3).
L'objet Reflect n'est pas un objet de fonction. Il n'a pas de méthode interne [[Construct]]; il n'est pas possible d'utiliser l'objet Reflect comme constructeur avec l' opérateur new . L'objet Reflect n'a pas non plus de méthode interne [[Call]]; il n'est pas possible d'invoquer l'objet Reflect en tant que fonction.
Cependant, il y a une brève explication sur son objectif dans ES Harmony :
Le module «@reflect» a plusieurs objectifs:
- Maintenant que nous avons des modules, un module «@reflect» est un endroit plus naturel pour de nombreuses méthodes de réflexion précédemment définies sur Object. À des fins de compatibilité descendante, il est peu probable que les méthodes statiques sur Object disparaissent. Cependant, de nouvelles méthodes devraient probablement être ajoutées au module «@reflect» plutôt qu'au constructeur Object.
- Une maison naturelle pour les proxies, évitant le besoin d'une liaison Proxy globale.
- La plupart des méthodes de ce module mappent un à un sur les interruptions Proxy. Les gestionnaires de proxy ont besoin de ces méthodes pour transférer facilement les opérations, comme indiqué ci-dessous.
Ainsi, l' Reflect
objet fournit un certain nombre de fonctions utilitaires, dont beaucoup semblent chevaucher les méthodes ES5 définies sur l'objet global.
Cependant, cela n'explique pas vraiment quels problèmes existants cela a l'intention de résoudre ou quelles fonctionnalités sont ajoutées. Je soupçonnais que cela pouvait être corrigé et en effet, les spécifications d'harmonie ci-dessus sont liées à une «implémentation approximative et non normative de ces méthodes» .
L'examen de ce code pourrait donner une (plus) idée de son utilisation, mais heureusement, il existe également un wiki qui décrit un certain nombre de raisons pour lesquelles l'objet Reflect est utile :
(J'ai copié (et formaté) le texte suivant pour référence future à partir de cela source car ce sont les seuls exemples que j'ai pu trouver. En plus de cela, ils ont du sens, ont déjà une bonne explication et touchent l' apply
exemple de la question .)
Valeurs de retour plus utiles
De nombreuses opérations dans Reflect
sont similaires aux opérations ES5 définies sur Object
, telles que Reflect.getOwnPropertyDescriptor
et Reflect.defineProperty
. Cependant, alors que Object.defineProperty(obj, name, desc)
sera soit retourné obj
lorsque la propriété a été définie avec succès, soit jeté un TypeError
sinon, Reflect.defineProperty(obj, name, desc)
est spécifié pour simplement renvoyer un booléen qui indique si la propriété a été définie avec succès ou non. Cela vous permet de refactoriser ce code:
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
Pour ça:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
Les autres méthodes qui renvoient un tel état de réussite booléen sont Reflect.set
(pour mettre à jour une propriété), Reflect.deleteProperty
(pour supprimer une propriété), Reflect.preventExtensions
(pour rendre un objet non extensible) et Reflect.setPrototypeOf
(pour mettre à jour le lien prototype d'un objet).
Opérations de premier ordre
Dans ES5, le moyen de détecter si un objet obj
définit ou hérite d'un certain nom de propriété est d'écrire (name in obj)
. De même, pour supprimer une propriété, on utilise delete obj[name]
. Bien que la syntaxe dédiée soit agréable et courte, cela signifie également que vous devez explicitement encapsuler ces opérations dans des fonctions lorsque vous souhaitez transmettre l'opération en tant que valeur de première classe.
Avec Reflect
, ces opérations sont facilement définies comme des fonctions de première classe:
Reflect.has(obj, name)
est l'équivalent fonctionnel de (name in obj)
et Reflect.deleteProperty(obj, name)
est une fonction qui fait la même chose quedelete obj[name].
Application de fonction plus fiable
Dans ES5, quand on veut appeler une fonction f
avec un nombre variable d'arguments emballés sous forme de tableau args
et lier la this
valeur à obj
, on peut écrire:
f.apply(obj, args)
Cependant, f
pourrait être un objet qui définit intentionnellement ou non sa propre apply
méthode. Lorsque vous voulez vraiment vous assurer que la apply
fonction intégrée est appelée, on écrit généralement:
Function.prototype.apply.call(f, obj, args)
Non seulement cela est verbeux, mais cela devient rapidement difficile à comprendre. Avec Reflect
, vous pouvez désormais effectuer un appel de fonction fiable de manière plus courte et plus simple à comprendre:
Reflect.apply(f, obj, args)
Constructeurs d'arguments variables
Imaginez que vous vouliez appeler une fonction constructeur avec un nombre variable d'arguments. Dans ES6, grâce à la nouvelle syntaxe de diffusion, il sera possible d'écrire du code comme:
var obj = new F(...args)
Dans ES5, c'est plus difficile à écrire, car on ne peut utiliser F.apply
ou F.call
appeler qu'une fonction avec un nombre variable d'arguments, mais il n'y a pas de F.construct
fonction à new
la fonction avec un nombre variable d'arguments. Avec Reflect
, on peut maintenant écrire, dans ES5:
var obj = Reflect.construct(F, args)
Comportement de transfert par défaut pour les interruptions proxy
Lorsque vous utilisez des Proxy
objets pour envelopper des objets existants, il est très courant d'intercepter une opération, de faire quelque chose, puis de «faire la chose par défaut», ce qui consiste généralement à appliquer l'opération interceptée à l'objet enveloppé. Par exemple, disons que je veux simplement enregistrer tous les accès aux propriétés d'un objet obj
:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
Les API Reflect
et ont été conçues en tandem , de sorte que pour chaque trap, il existe une méthode correspondante sur laquelle "fait la chose par défaut". Par conséquent, chaque fois que vous avez envie de "faire la chose par défaut" dans un gestionnaire de proxy, la bonne chose à faire est de toujours appeler la méthode correspondante dans l' objet:Proxy
Proxy
Reflect
Reflect
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
Le type de retour des Reflect
méthodes est garanti compatible avec le type de retour des Proxy
traps.
Contrôler la liaison des accesseurs
Dans ES5, il est assez facile de faire un accès à une propriété générique ou une mise à jour de propriété. Par exemple:
var name = ...
obj[name]
obj[name] = value
Les méthodes Reflect.get
et Reflect.set
vous permettent de faire la même chose, mais acceptent en plus comme dernier argument facultatif un receiver
paramètre qui vous permet de définir explicitement la this
liaison lorsque la propriété que vous obtenez / définissez est un accesseur:
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
Ceci est parfois utile lorsque vous encapsulez obj
et que vous voulez que tous les auto-envois dans l'accesseur soient redirigés vers votre wrapper, par exemple si obj
est défini comme:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
L'appel Reflect.get(obj, "foo", wrapper)
entraînera le this.bar()
réacheminement de l' appel vers wrapper
.
Évitez l'héritage __proto__
Sur certains navigateurs, __proto__
est défini comme une propriété spéciale qui donne accès au prototype d'un objet. ES5 a standardisé une nouvelle méthode Object.getPrototypeOf(obj)
pour interroger le prototype. Reflect.getPrototypeOf(obj)
fait exactement la même chose, sauf que Reflect
définit également un correspondant Reflect.setPrototypeOf(obj, newProto)
pour définir le prototype de l'objet. Il s'agit du nouveau moyen conforme à ES6 de mettre à jour le prototype d'un objet.
Notez que: existe setPrototypeOf
aussi surObject
(comme indiqué correctement par le commentaire de Knu )!
EDIT:
Note d' accompagnement (adressant les commentaires au Q): Il y a une réponse courte et simple sur «Q: Modules ES6 vs importations HTML» qui explique Realms
et Loader
objets.
Une autre explication est offerte par ce lien :
Un objet de domaine fait abstraction de la notion d'environnement global distinct, avec son propre objet global, une copie de la bibliothèque standard et des "intrinsèques" (objets standard qui ne sont pas liés à des variables globales, comme la valeur initiale d'Object.prototype).
Web extensible : c'est l'équivalent dynamique d'une même origine
<iframe>
sans DOM.
A noter cependant: tout cela est encore à l'état de brouillon, ce n'est pas une spécification gravée dans la pierre! C'est ES6, alors gardez à l'esprit la compatibilité du navigateur!
J'espère que cela t'aides!
Reflect
n'est qu'un conteneur pourRealm
et desLoader
objets, mais je ne sais pas non plus ce que font ces derniers.