J'ai vu un talon vierge sur MDN il y a quelque temps pour l' Reflect
objet en javascript, mais je ne peux rien trouver sur Google pendant toute ma vie. Aujourd'hui, j'ai trouvé cet http://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect-object et cela ressemble à l'objet Proxy en dehors du domaine et des fonctionnalités du chargeur.
Fondamentalement, je ne sais pas si cette page que j'ai trouvée explique uniquement comment implémenter Reflect ou si je ne comprends tout simplement pas sa formulation. Quelqu'un pourrait-il s'il vous plaît m'expliquer généralement ce que les méthodes de Reflect
faire?
Par exemple, sur la page que j'ai trouvée, il est dit que l'appel Reflect.apply ( target, thisArgument, argumentsList )
"retournera le résultat de l'appel de la méthode interne [[Call]] de la cible avec les arguments thisArgument et args." mais en quoi est-ce différent de simplement appeler target.apply(thisArgument, argumentsList)
?
Mise à jour:
Grâce à @Blue, j'ai trouvé cette page sur le wiki http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect
qui, à ma connaissance, indique que l'objet Reflect
fournit des versions de méthode de tous les actions qui peuvent être piégées par des proxys pour faciliter le transfert. Mais cela me semble un peu bizarre car je ne vois pas en quoi c'est entièrement nécessaire. Mais il semble faire un peu plus que cela, en particulier le pair qui dit double-lifting
mais qui pointe vers l'ancienne spécification du proxy /
la source
Reflect
n'est qu'un conteneur pourRealm
et desLoader
objets, mais je ne sais pas non plus ce que font ces derniers.Reflect.Loader
etReflect.Realm
avoir quelque chose à avec la fonctionnalité de module de surcharge?isExtensible
,ownKeys
etc. ES 6, avec des classes réelles, ce qui est utile pour en savoir plus sur une classe (target
en 16.1.2 , je pense).Réponses:
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 lesReflect
méthodes de -object et indique uniquement ce qui suit surReflect
-object lui-même:Cependant, il y a une brève explication sur son objectif dans ES Harmony :
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 surObject
, telles queReflect.getOwnPropertyDescriptor
etReflect.defineProperty
. Cependant, alors queObject.defineProperty(obj, name, desc)
sera soit retournéobj
lorsque la propriété a été définie avec succès, soit jeté unTypeError
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); // property defined successfully } catch (e) { // possible failure (and might accidentally catch the wrong exception) }
Pour ça:
if (Reflect.defineProperty(obj, name, desc)) { // success } else { // failure }
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) etReflect.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 utilisedelete 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)
etReflect.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 tableauargs
et lier lathis
valeur àobj
, on peut écrire:Cependant,
f
pourrait être un objet qui définit intentionnellement ou non sa propreapply
méthode. Lorsque vous voulez vraiment vous assurer que laapply
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
ouF.call
appeler qu'une fonction avec un nombre variable d'arguments, mais il n'y a pas deF.construct
fonction ànew
la fonction avec un nombre variable d'arguments. AvecReflect
, 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 objetobj
:var loggedObj = new Proxy(obj, { get: function(target, name) { console.log("get", target, name); // now do the default thing } });
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 desProxy
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 = ... // get property name as a string obj[name] // generic property lookup obj[name] = value // generic property update
Les méthodes
Reflect.get
etReflect.set
vous permettent de faire la même chose, mais acceptent en plus comme dernier argument facultatif unreceiver
paramètre qui vous permet de définir explicitement lathis
liaison lorsque la propriété que vous obtenez / définissez est un accesseur: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)
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 siobj
est défini comme:var obj = { get foo() { return this.bar(); }, bar: function() { ... } }
L'appel
Reflect.get(obj, "foo", wrapper)
entraînera lethis.bar()
réacheminement de l' appel verswrapper
.É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éthodeObject.getPrototypeOf(obj)
pour interroger le prototype.Reflect.getPrototypeOf(obj)
fait exactement la même chose, sauf queReflect
définit également un correspondantReflect.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
etLoader
objets.Une autre explication est offerte par ce lien :
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!
la source
Reflect.apply
ettarget.apply
? Ou que dois-je ajouter avant la fin de la prime?Object
.Reflect.get
comme implémentation par défaut pour le proxy get ne fonctionne pas correctement si vous effectuez un proxy d'un objet avec des propriétés de prototype. Il se plaint simplement que cela ne fonctionne pas. Cependant, si vous utilisez à la placeReflect.get(target, property)
sans passer lereceiver
, cela fonctionne.target
est la cible d'origine que le proxy enveloppe, tandis quereceiver
le proxy lui-même. Mais encore une fois, cela pourrait être différent si vous parvenez à accéder aux propriétés différemment.En passant par le projet de document trouvé sur le wiki,
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
Nous obtenons la ligne sur "un seul objet ordinaire" qu'elle clarifie dans le brouillon. Il contient également les définitions de fonction.
Le wiki doit être fiable car vous pouvez trouver un lien vers celui-ci sur le site Web emcascript
http://www.ecmascript.org/dev.php
J'ai trouvé le premier lien par google et je n'ai pas eu de chance de le trouver en cherchant directement sur le wiki.
la source