UPDATE 2015:
Come sottolineato da 7 's risposta , ora che ES6 (ECMAScript 2015) è stato finalizzato, documentazione più appropriata è ora disponibile:
Risposta originale (per comprensione (storica) ed esempi extra) :
L' Reflection proposalsembra essere progredita al Progetto ECMAScript 6 Specification . Questo documento attualmente delinea ilReflect metodi di -object e afferma solo quanto segue Reflectsull'oggetto stesso:
L'oggetto Reflect è un singolo oggetto ordinario.
Il valore dello slot interno [[Prototype]] dell'oggetto Reflect è l'oggetto prototipo Object incorporato standard (19.1.3).
L'oggetto Reflect non è un oggetto funzione. Non ha un metodo interno [[Construct]]; non è possibile utilizzare l'oggetto Reflect come costruttore con l'estensione nuovo operatore . L'oggetto Reflect non dispone inoltre di un metodo interno [[Call]]; non è possibile richiamare l'oggetto Reflect come funzione.
Tuttavia, c'è una breve spiegazione sul suo scopo in ES Harmony :
Il modulo "@reflect" ha molteplici scopi:
- Ora che abbiamo i moduli, un modulo "@reflect" è un luogo più naturale per molti dei metodi di riflessione precedentemente definiti in Object. Per motivi di compatibilità con le versioni precedenti, è improbabile che i metodi statici su Object scompaiano. Tuttavia, è probabile che nuovi metodi vengano aggiunti al modulo "@reflect" piuttosto che al costruttore Object.
- Una casa naturale per i proxy, che evita la necessità di un'associazione proxy globale.
- La maggior parte dei metodi in questo modulo mappa uno a uno su trap proxy. I gestori proxy necessitano di questi metodi per inoltrare comodamente le operazioni, come mostrato di seguito.
Quindi, l' Reflectoggetto fornisce una serie di funzioni di utilità, molte delle quali sembrano sovrapporsi ai metodi ES5 definiti sull'Oggetto globale.
Tuttavia, ciò non spiega realmente quali problemi esistenti si intende risolvere o quali funzionalità vengono aggiunte. Sospettavo che questo potesse essere attenuato e, in effetti, le specifiche dell'armonia di cui sopra si collegano a una "implementazione non normativa e approssimativa di questi metodi" .
L'esame di quel codice potrebbe dare (ulteriori) idee sul suo utilizzo, ma per fortuna c'è anche un wiki che delinea una serie di ragioni per cui l'oggetto Reflect è utile :
(Ho copiato (e formattato) il testo seguente per riferimento futuro da quello fonte in quanto sono gli unici esempi che sono riuscito a trovare. Inoltre, hanno senso, hanno già una buona spiegazione e toccano l' applyesempio della domanda .)
Valori di ritorno più utili
Molte operazioni in Reflectsono simili alle operazioni ES5 definite su Object, come Reflect.getOwnPropertyDescriptore Reflect.defineProperty. Tuttavia, mentre Object.defineProperty(obj, name, desc)verrà restituito objquando la proprietà è stata definita correttamente o verrà generato un TypeErroraltro, Reflect.defineProperty(obj, name, desc)è specificato che restituisca semplicemente un valore booleano che indica se la proprietà è stata definita correttamente. Ciò ti consente di eseguire il refactoring di questo codice:
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
A questa:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
Altri metodi che restituiscono un tale stato di successo booleano sono Reflect.set(per aggiornare una proprietà), Reflect.deleteProperty(per eliminare una proprietà), Reflect.preventExtensions(per rendere un oggetto non estensibile) e Reflect.setPrototypeOf(per aggiornare il collegamento prototipo di un oggetto).
Operazioni di prima classe
In ES5, il modo per rilevare se un oggetto objdefinisce o eredita un determinato nome di proprietà è scrivere (name in obj). Allo stesso modo, per eliminare una proprietà, si usa delete obj[name]. Sebbene la sintassi dedicata sia carina e breve, significa anche che devi racchiudere esplicitamente queste operazioni in funzioni quando vuoi passare l'operazione come valore di prima classe.
Con Reflect, queste operazioni sono prontamente definite come funzioni di prima classe:
Reflect.has(obj, name)è l'equivalente funzionale di (name in obj)ed Reflect.deleteProperty(obj, name)è una funzione che fa lo stesso didelete obj[name].
Applicazione di funzioni più affidabile
In ES5, quando si vuole chiamare una funzione fcon un numero variabile di argomenti impacchettati come un array argse vincolando il thisvalore a obj, si può scrivere:
f.apply(obj, args)
Tuttavia, fpotrebbe essere un oggetto che intenzionalmente o non intenzionalmente definisce il proprio applymetodo. Quando vuoi davvero assicurarti che la applyfunzione incorporata sia chiamata, in genere si scrive:
Function.prototype.apply.call(f, obj, args)
Non solo questo è prolisso, ma diventa rapidamente difficile da capire. Con Reflect, ora puoi effettuare una chiamata di funzione affidabile in un modo più breve e più facile da capire:
Reflect.apply(f, obj, args)
Costruttori di argomenti variabili
Immagina di voler chiamare una funzione di costruzione con un numero variabile di argomenti. In ES6, grazie alla nuova sintassi spread, sarà possibile scrivere codice come:
var obj = new F(...args)
In ES5, questo è più difficile da scrivere, perché si può solo usare F.applyo F.callchiamare una funzione con un numero variabile di argomenti, ma non c'è nessuna F.constructfunzione per newla funzione con un numero variabile di argomenti. Con Reflect, ora si può scrivere, in ES5:
var obj = Reflect.construct(F, args)
Comportamento di inoltro predefinito per trap proxy
Quando si usano Proxyoggetti per racchiudere oggetti esistenti, è molto comune intercettare un'operazione, fare qualcosa e poi "fare la cosa predefinita", che è tipicamente applicare l'operazione intercettata all'oggetto avvolto. Ad esempio, diciamo che voglio semplicemente registrare tutti gli accessi alle proprietà di un oggetto obj:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
Le API Reflecte sono state progettate in tandem , in modo tale che per ogni trap esiste un metodo corrispondente che "fa la cosa predefinita". Quindi, ogni volta che ti ritrovi a voler "fare la cosa predefinita" all'interno di un gestore Proxy, la cosa corretta da fare è chiamare sempre il metodo corrispondente nell'oggetto:ProxyProxyReflectReflect
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
ReflectÈ garantito che il tipo restituito dei metodi sia compatibile con il tipo restituito dei Proxytrap.
Controlla questo collegamento delle funzioni di accesso
In ES5 è abbastanza facile eseguire un accesso generico alla proprietà o un aggiornamento della proprietà. Per esempio:
var name = ...
obj[name]
obj[name] = value
I metodi Reflect.gete Reflect.setti consentono di fare la stessa cosa, ma in aggiunta accetta come ultimo argomento opzionale un receiverparametro che ti consente di impostare esplicitamente il this-binding quando la proprietà che ottieni / imposta è una funzione di accesso:
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
Questo è occasionalmente utile quando si esegue il wrapping obje si desidera che qualsiasi autoinvio all'interno dell'accessor objvenga reindirizzato al wrapper, ad esempio if è definito come:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
La chiamata Reflect.get(obj, "foo", wrapper)causerà il this.bar()reindirizzamento della chiamata a wrapper.
Evita l'eredità __proto__
In alcuni browser, __proto__è definita come una proprietà speciale che dà accesso al prototipo di un oggetto. ES5 ha standardizzato un nuovo metodo Object.getPrototypeOf(obj)per interrogare il prototipo. Reflect.getPrototypeOf(obj)fa esattamente lo stesso, tranne che Reflectdefinisce anche un corrispondente Reflect.setPrototypeOf(obj, newProto)per impostare il prototipo dell'oggetto. Questo è il nuovo modo conforme a ES6 per aggiornare il prototipo di un oggetto.
Si noti che: setPrototypeOf anche esisteObject (come giustamente sottolineato da Knu 's commenti )!
EDIT:
Nota a margine (indirizzando i commenti alla domanda ): c'è una risposta breve e semplice su "Q: moduli ES6 e importazioni HTML" che spiega Realmse Loaderoggetti.
Un'altra spiegazione è offerta da questo link :
Un oggetto realm astrae la nozione di un ambiente globale distinto, con il proprio oggetto globale, copia della libreria standard e "intrinseci" (oggetti standard che non sono vincolati a variabili globali, come il valore iniziale di Object.prototype).
Web estensibile : questo è l'equivalente dinamico di una stessa origine
<iframe>senza DOM.
Da segnalare però: tutto questo è ancora in bozza, non si tratta di una specifica incisa nella pietra! È ES6, quindi tieni presente la compatibilità del browser!
Spero che sia di aiuto!
Reflectè solo un contenitore per oggettiRealmeLoader, ma non so nemmeno cosa facciano questi ultimi.