ATUALIZAÇÃO 2015:
Como apontado por 7ª 's resposta , agora que ES6 (ECMAScript 2015) foi finalizado, a documentação mais apropriado já está disponível:
Resposta original (para compreensão (histórica) e exemplos extras) :
O Reflection proposal
parece ter progredido para a Especificação ECMAScript 6 do Projeto . Este documento atualmente descreve os Reflect
métodos do -objeto e afirma apenas o seguinte sobre o Reflect
próprio -objeto:
O objeto Reflect é um único objeto comum.
O valor do slot interno [[Prototype]] do objeto Reflect é o objeto de protótipo padrão interno do objeto (19.1.3).
O objeto Reflect não é um objeto de função. Ele não tem um método interno [[Construct]]; não é possível usar o objeto Reflect como um construtor com o novo operador. O objeto Reflect também não possui um método interno [[Call]]; não é possível invocar o objeto Reflect como uma função.
No entanto, há uma breve explicação sobre seu propósito no ES Harmony :
O módulo “@reflect” tem várias finalidades:
- Agora que temos módulos, um módulo “@reflect” é um lugar mais natural para muitos dos métodos de reflexão previamente definidos em Object. Para fins de compatibilidade com versões anteriores, é improvável que os métodos estáticos em Object desapareçam. No entanto, novos métodos provavelmente devem ser adicionados ao módulo “@reflect” ao invés do construtor Object.
- Um lar natural para proxies, evitando a necessidade de uma ligação de proxy global.
- A maioria dos métodos neste módulo mapeia um a um em armadilhas de proxy. Os manipuladores de proxy precisam desses métodos para encaminhar convenientemente as operações, conforme mostrado abaixo.
Portanto, o Reflect
objeto fornece várias funções de utilitário, muitas das quais parecem se sobrepor aos métodos ES5 definidos no objeto global.
No entanto, isso não explica realmente quais problemas existentes isso pretende resolver ou quais funcionalidades são adicionadas. Suspeitei que isso pudesse ser corrigido e, de fato, as especificações de harmonia acima se vinculam a uma 'implementação aproximada não normativa desses métodos' .
Examinar esse código pode dar (mais) idéias sobre seu uso, mas felizmente também há um wiki que descreve uma série de razões pelas quais o objeto Reflect é útil :
(Copiei (e formatei) o seguinte texto para referência futura daquele fonte pois são os únicos exemplos que consegui encontrar. Além disso, fazem sentido, já têm uma boa explicação e tocam no apply
exemplo da pergunta .)
Valores de retorno mais úteis
Muitas operações em Reflect
são semelhantes às operações ES5 definidas em Object
, como Reflect.getOwnPropertyDescriptor
e Reflect.defineProperty
. No entanto, enquanto Object.defineProperty(obj, name, desc)
irá retornar obj
quando a propriedade foi definida com sucesso, ou lançar um TypeError
caso contrário, Reflect.defineProperty(obj, name, desc)
é especificado para simplesmente retornar um booleano que indica se a propriedade foi definida com sucesso ou não. Isso permite que você refatore este código:
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
Para isso:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
Outros métodos que retornam esse status de sucesso booleano são Reflect.set
(para atualizar uma propriedade), Reflect.deleteProperty
(para excluir uma propriedade), Reflect.preventExtensions
(para tornar um objeto não extensível) e Reflect.setPrototypeOf
(para atualizar o link de protótipo de um objeto).
Operações de primeira classe
No ES5, a maneira de detectar se um objeto obj
define ou herda um determinado nome de propriedade é escrever (name in obj)
. Da mesma forma, para excluir uma propriedade, usa-se delete obj[name]
. Embora a sintaxe dedicada seja boa e curta, também significa que você deve envolver explicitamente essas operações em funções quando quiser passar a operação como um valor de primeira classe.
Com Reflect
, essas operações são prontamente definidas como funções de primeira classe:
Reflect.has(obj, name)
é o equivalente funcional de (name in obj)
e Reflect.deleteProperty(obj, name)
é uma função que faz o mesmo quedelete obj[name].
Aplicação de função mais confiável
No ES5, quando se deseja chamar uma função f
com um número variável de argumentos empacotados como uma matriz args
e vincular o this
valor a obj
, pode-se escrever:
f.apply(obj, args)
No entanto, f
pode ser um objeto que define intencionalmente ou não seu próprio apply
método. Quando você realmente deseja ter certeza de que a apply
função integrada é chamada, normalmente escreve-se:
Function.prototype.apply.call(f, obj, args)
Não é apenas prolixo, mas rapidamente se torna difícil de entender. Com o Reflect
, agora você pode fazer uma chamada de função confiável de uma forma mais curta e fácil de entender:
Reflect.apply(f, obj, args)
Construtores de argumento variável
Imagine que você deseja chamar uma função construtora com um número variável de argumentos. No ES6, graças à nova sintaxe difundida, será possível escrever códigos como:
var obj = new F(...args)
No ES5, isso é mais difícil de escrever, porque só se pode usar F.apply
ou F.call
chamar uma função com um número variável de argumentos, mas não há F.construct
função para new
a função com um número variável de argumentos. Com Reflect
, agora é possível escrever, em ES5:
var obj = Reflect.construct(F, args)
Comportamento de encaminhamento padrão para armadilhas de proxy
Ao usar Proxy
objetos para encapsular objetos existentes, é muito comum interceptar uma operação, fazer algo e, em seguida, "fazer a coisa padrão", que normalmente é aplicar a operação interceptada ao objeto encapsulado. Por exemplo, digamos que eu queira simplesmente registrar todos os acessos de propriedade a um objeto obj
:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
As APIs Reflect
e foram projetadas em conjunto , de forma que para cada armadilha, existe um método correspondente que "faz a coisa padrão". Portanto, sempre que você quiser "fazer o padrão" dentro de um manipulador Proxy, a coisa correta a fazer é sempre chamar o método correspondente no objeto:Proxy
Proxy
Reflect
Reflect
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
O tipo de retorno dos Reflect
métodos tem garantia de compatibilidade com o tipo de retorno das Proxy
armadilhas.
Controlar esta ligação de acessores
No ES5 é bastante fácil fazer um acesso de propriedade genérico ou atualização de propriedade. Por exemplo:
var name = ...
obj[name]
obj[name] = value
Os métodos Reflect.get
e Reflect.set
permitem que você faça a mesma coisa, mas, adicionalmente, aceitam como último argumento opcional um receiver
parâmetro que permite definir explicitamente a this
-binding quando a propriedade que você obtém / define é um acessador:
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
Isso é ocasionalmente útil quando você está empacotando obj
e deseja que qualquer envio automático dentro do acessador seja redirecionado para seu wrapper, por exemplo, se obj
for definido como:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
Chamar Reflect.get(obj, "foo", wrapper)
fará com que a this.bar()
chamada seja redirecionada para wrapper
.
Evite legado __proto__
Em alguns navegadores, __proto__
é definido como uma propriedade especial que dá acesso ao protótipo de um objeto. ES5 padronizou um novo método Object.getPrototypeOf(obj)
para consultar o protótipo. Reflect.getPrototypeOf(obj)
faz exatamente o mesmo, exceto que Reflect
também define um correspondente Reflect.setPrototypeOf(obj, newProto)
para definir o protótipo do objeto. Esta é a nova maneira compatível com ES6 de atualizar o protótipo de um objeto.
Note-se que: setPrototypeOf
também existe emObject
(como corretamente apontado por Knu 's comentário )!
EDIT:
Nota lateral (endereçando comentários ao Q): Há uma resposta curta e simples em 'Q: Módulos ES6 vs. Importações de HTML' que explica Realms
e Loader
objeta.
Outra explicação é oferecida por este link :
Um objeto de domínio abstrai a noção de um ambiente global distinto, com seu próprio objeto global, cópia da biblioteca padrão e "intrínsecos" (objetos padrão que não estão vinculados a variáveis globais, como o valor inicial de Object.prototype).
Web extensível : este é o equivalente dinâmico de uma mesma origem
<iframe>
sem DOM.
Vale a pena mencionar: tudo isso ainda está em projeto, esta não é uma especificação gravada na pedra! É ES6, portanto, mantenha a compatibilidade do navegador em mente!
Espero que isto ajude!
Reflect
é apenas um contêiner para objetosRealm
eLoader
, mas também não sei o que estes fazem.