UPDATE 2015:
Wie aus der Antwort von 7th hervorgeht , ist nach Abschluss von ES6 (ECMAScript 2015) eine geeignetere Dokumentation verfügbar:
Ursprüngliche Antwort (für (historisches) Verständnis und zusätzliche Beispiele) :
Der Reflection proposalscheint zum Entwurf der ECMAScript 6-Spezifikation übergegangen zu sein . Dieses Dokument beschreibt derzeit die ReflectMethoden des Objekts und gibt nur Folgendes über das ReflectObjekt selbst an:
Das Reflect-Objekt ist ein einzelnes gewöhnliches Objekt.
Der Wert des internen Steckplatzes des Reflect-Objekts ist das standardmäßige integrierte Objektprototypobjekt (19.1.3).
Das Reflect-Objekt ist kein Funktionsobjekt. Es gibt keine interne Methode; Es ist nicht möglich, das Reflect-Objekt als Konstruktor mit dem neuen Operator zu verwenden. Das Reflect-Objekt verfügt auch nicht über eine interne Methode [[Call]]. Es ist nicht möglich, das Reflect-Objekt als Funktion aufzurufen.
Es gibt jedoch eine kurze Erklärung zu seinem Zweck in ES Harmony :
Das Modul "@reflect" dient mehreren Zwecken:
- Jetzt, da wir Module haben, ist ein "@reflect" -Modul ein natürlicherer Ort für viele der zuvor für Object definierten Reflexionsmethoden. Aus Gründen der Abwärtskompatibilität ist es unwahrscheinlich, dass die statischen Methoden für Object verschwinden. Es sollten jedoch wahrscheinlich neue Methoden zum Modul "@reflect" und nicht zum Objektkonstruktor hinzugefügt werden.
- Ein natürliches Zuhause für Proxys, ohne dass eine globale Proxy-Bindung erforderlich ist.
- Die meisten Methoden in diesem Modul ordnen Eins-zu-Eins Proxy-Traps zu. Proxy-Handler benötigen diese Methoden, um Vorgänge wie unten gezeigt bequem weiterzuleiten.
Daher bietet das ReflectObjekt eine Reihe von Dienstprogrammfunktionen, von denen sich viele mit den im globalen Objekt definierten ES5-Methoden zu überschneiden scheinen.
Dies erklärt jedoch nicht wirklich, welche vorhandenen Probleme dadurch gelöst werden sollen oder welche Funktionen hinzugefügt werden. Ich vermutete, dass dies abgeglichen werden könnte, und tatsächlich verweist die obige Harmonie-Spezifikation auf eine „nicht normative, ungefähre Implementierung dieser Methoden“ .
Das Untersuchen dieses Codes könnte (weitere) Ideen über seine Verwendung geben, aber zum Glück gibt es auch ein Wiki, das eine Reihe von Gründen aufzeigt, warum das Reflect-Objekt nützlich ist :
(Ich habe den folgenden Text kopiert (und formatiert), um später darauf zurückgreifen zu können Quelle, da sie die einzigen Beispiele sind, die ich finden konnte. Außerdem sind sie sinnvoll, haben bereits eine gute Erklärung und berühren das applyBeispiel der Frage .)
Weitere nützliche Rückgabewerte
Viele Operationen in Reflectähneln den auf definierten ES5-Operationen Objectwie Reflect.getOwnPropertyDescriptorund Reflect.defineProperty. Während Object.defineProperty(obj, name, desc)jedoch entweder zurückgegeben wird, objwenn die Eigenschaft erfolgreich definiert wurde, oder ein TypeErroranderes Reflect.defineProperty(obj, name, desc)ausgelöst wird, wird nur ein Boolescher Wert zurückgegeben, der angibt, ob die Eigenschaft erfolgreich definiert wurde oder nicht. Auf diese Weise können Sie diesen Code umgestalten:
try {
Object.defineProperty(obj, name, desc);
// property defined successfully
} catch (e) {
// possible failure (and might accidentally catch the wrong exception)
}
Dazu:
if (Reflect.defineProperty(obj, name, desc)) {
// success
} else {
// failure
}
Andere Methoden, die einen solchen booleschen Erfolgsstatus zurückgeben, sind Reflect.set(um eine Eigenschaft zu aktualisieren), Reflect.deleteProperty(um eine Eigenschaft zu löschen), Reflect.preventExtensions(um ein Objekt nicht erweiterbar zu machen) und Reflect.setPrototypeOf(um die Prototypverknüpfung eines Objekts zu aktualisieren).
Erstklassiger Betrieb
In ES5 können Sie feststellen, ob ein Objekt objeinen bestimmten Eigenschaftsnamen definiert oder erbt (name in obj). Ebenso verwendet man zum Löschen einer Eigenschaft delete obj[name]. Die dedizierte Syntax ist zwar nett und kurz, bedeutet aber auch, dass Sie diese Operationen explizit in Funktionen einschließen müssen, wenn Sie die Operation als erstklassigen Wert weitergeben möchten.
Mit Reflectkönnen diese Operationen leicht als erstklassige Funktionen definiert werden:
Reflect.has(obj, name)ist das funktionale Äquivalent von (name in obj)und Reflect.deleteProperty(obj, name)ist eine Funktion, die dasselbe tut wiedelete obj[name].
Zuverlässigere Funktionsanwendung
Wenn man in ES5 eine Funktion fmit einer variablen Anzahl von Argumenten aufrufen möchte, die als Array gepackt sind argsund an die der thisWert gebunden ist obj, kann man schreiben:
f.apply(obj, args)
Könnte fjedoch ein Objekt sein, das absichtlich oder unbeabsichtigt seine eigene applyMethode definiert . Wenn Sie wirklich sicherstellen möchten, dass die integrierte applyFunktion aufgerufen wird, schreibt man normalerweise:
Function.prototype.apply.call(f, obj, args)
Dies ist nicht nur ausführlich, es wird auch schnell schwer zu verstehen. Mit Reflectkönnen Sie jetzt einen zuverlässigen Funktionsaufruf kürzer und verständlicher durchführen:
Reflect.apply(f, obj, args)
Konstruktoren mit variablen Argumenten
Stellen Sie sich vor, Sie möchten eine Konstruktorfunktion mit einer variablen Anzahl von Argumenten aufrufen. In ES6 ist es dank der neuen Spread-Syntax möglich, Code wie folgt zu schreiben:
var obj = new F(...args)
In ES5 ist dies schwieriger zu schreiben, da nur eine Funktion mit einer variablen Anzahl von Argumenten verwendet F.applyoder F.callaufgerufen werden kann, die Funktion mit einer variablen Anzahl von Argumenten jedoch keine F.constructFunktion hat new. Mit Reflectkann man jetzt in ES5 schreiben:
var obj = Reflect.construct(F, args)
Standardweiterleitungsverhalten für Proxy-Traps
Wenn Sie ProxyObjekte verwenden, um vorhandene Objekte zu verpacken, ist es sehr üblich, eine Operation abzufangen, etwas zu tun und dann "die Standardeinstellung" auszuführen, bei der die abgefangene Operation normalerweise auf das umschlossene Objekt angewendet wird. Angenommen, ich möchte einfach alle Eigenschaftszugriffe auf ein Objekt protokollieren obj:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
// now do the default thing
}
});
Die Reflectund ProxyAPIs wurden zusammen entworfen , sodass für jede ProxyFalle eine entsprechende Methode vorhanden ist Reflect, die "die Standardeinstellung ausführt". Wenn Sie also feststellen, dass Sie die Standardeinstellung in einem Proxy-Handler ausführen möchten, müssen Sie immer die entsprechende Methode im ReflectObjekt aufrufen :
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
Der Rückgabetyp der ReflectMethoden ist garantiert mit dem Rückgabetyp der ProxyTraps kompatibel .
Kontrollieren Sie diese Bindung von Accessoren
In ES5 ist es ziemlich einfach, einen allgemeinen Eigenschaftszugriff oder eine Eigenschaftsaktualisierung durchzuführen. Zum Beispiel:
var name = ... // get property name as a string
obj[name] // generic property lookup
obj[name] = value // generic property update
Mit den Methoden Reflect.getund Reflect.setkönnen Sie dasselbe tun, aber zusätzlich als letztes optionales Argument einen receiverParameter akzeptieren , mit dem Sie die thisBindung explizit festlegen können, wenn die Eigenschaft, die Sie erhalten / festlegen, ein Accessor ist:
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)
Dies ist gelegentlich nützlich, wenn Sie einpacken objund möchten, dass alle Selbstsendungen innerhalb des Accessors an Ihren Wrapper weitergeleitet werden, z. B. wenn Folgendes objdefiniert ist:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
Durch einen Anruf Reflect.get(obj, "foo", wrapper)wird der this.bar()Anruf umgeleitet wrapper.
Vermeiden Sie Vermächtnis __proto__
Wird in einigen Browsern __proto__als spezielle Eigenschaft definiert, die den Zugriff auf den Prototyp eines Objekts ermöglicht. ES5 standardisierte eine neue Methode Object.getPrototypeOf(obj)zur Abfrage des Prototyps. Reflect.getPrototypeOf(obj)macht genau das gleiche, außer dass Reflectauch ein entsprechender definiert wird Reflect.setPrototypeOf(obj, newProto), um den Prototyp des Objekts festzulegen. Dies ist die neue ES6-kompatible Methode zum Aktualisieren des Prototyps eines Objekts.
Beachten Sie, dass: setPrototypeOf auch vorhanden aufObject (wie korrekt darauf hingewiesen Knu ‚s Kommentar )!
BEARBEITEN:
Randnotiz (Adressieren von Kommentaren zum Q): Es gibt eine kurze und einfache Antwort zu 'Q: ES6-Module vs. HTML-Importe' , die erklärt Realmsund LoaderObjekte.
Eine weitere Erklärung bietet dieser Link :
Ein Realm-Objekt abstrahiert den Begriff einer bestimmten globalen Umgebung mit einem eigenen globalen Objekt, einer Kopie der Standardbibliothek und "intrinsics" (Standardobjekte, die nicht an globale Variablen gebunden sind, wie der Anfangswert von Object.prototype).
Extensible Web : Dies ist das dynamische Äquivalent eines Ursprungs
<iframe>ohne DOM.
Erwähnenswert: All dies ist noch im Entwurf, dies ist keine in Stein gemeißelte Spezifikation! Es ist ES6, denken Sie also an die Browserkompatibilität!
Hoffe das hilft!
Reflectist es nur ein Container fürRealmundLoaderObjekte, aber ich weiß auch nicht, was letztere tun.