Eu vi um esboço em branco no MDN um tempo atrás para o Reflect
objeto em javascript, mas não consigo encontrar nada no Google. Hoje encontrei este http://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect-object e parece semelhante ao objeto Proxy, independentemente do domínio e da funcionalidade do carregador.
Basicamente, não sei se esta página que encontrei apenas explica como implementar o Reflect ou se simplesmente não consigo entender seu texto. Alguém poderia me explicar em geral quais são os métodos de Reflect
fazer?
Por exemplo, na página que encontrei diz que a chamada Reflect.apply ( target, thisArgument, argumentsList )
irá "Retornar o resultado da chamada do método interno [[Call]] de destino com os argumentos thisArgument e args." mas como isso é diferente de apenas ligar target.apply(thisArgument, argumentsList)
?
Atualizar:
Graças a @Blue, encontrei esta página no wiki http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect
que, pelo que sei,
diz que o objeto refletido fornece versões de método de todos as ações que podem ser interceptadas por proxies para facilitar o encaminhamento. Mas isso parece um pouco estranho para mim, já que não vejo como é totalmente necessário. Mas parece fazer um pouco mais do que isso, particularmente o par que diz, double-lifting
mas que aponta para a antiga especificação de proxy /
fonte
Reflect
é apenas um contêiner para objetosRealm
eLoader
, mas também não sei o que estes fazem.Reflect.Loader
eReflect.Realm
tem algo a ver com a funcionalidade de módulo de sobrecarga?isExtensible
,ownKeys
etc. Em ES 6, com aulas reais, isto é útil para descobrir mais sobre uma classe (target
em 16.1.2 eu acho).Respostas:
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 osReflect
métodos do -objeto e afirma apenas o seguinte sobre oReflect
próprio -objeto:No entanto, há uma breve explicação sobre seu propósito no ES Harmony :
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 emObject
, comoReflect.getOwnPropertyDescriptor
eReflect.defineProperty
. No entanto, enquantoObject.defineProperty(obj, name, desc)
irá retornarobj
quando a propriedade foi definida com sucesso, ou lançar umTypeError
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); // property defined successfully } catch (e) { // possible failure (and might accidentally catch the wrong exception) }
Para isso:
if (Reflect.defineProperty(obj, name, desc)) { // success } else { // failure }
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) eReflect.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-sedelete 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)
eReflect.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 matrizargs
e vincular othis
valor aobj
, pode-se escrever:No entanto,
f
pode ser um objeto que define intencionalmente ou não seu próprioapply
método. Quando você realmente deseja ter certeza de que aapply
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
ouF.call
chamar uma função com um número variável de argumentos, mas não háF.construct
função paranew
a função com um número variável de argumentos. ComReflect
, 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 objetoobj
:var loggedObj = new Proxy(obj, { get: function(target, name) { console.log("get", target, name); // now do the default thing } });
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 dasProxy
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 = ... // get property name as a string obj[name] // generic property lookup obj[name] = value // generic property update
Os métodos
Reflect.get
eReflect.set
permitem que você faça a mesma coisa, mas, adicionalmente, aceitam como último argumento opcional umreceiver
parâmetro que permite definir explicitamente athis
-binding quando a propriedade que você obtém / define é um acessador: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)
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, seobj
for definido como:var obj = { get foo() { return this.bar(); }, bar: function() { ... } }
Chamar
Reflect.get(obj, "foo", wrapper)
fará com que athis.bar()
chamada seja redirecionada parawrapper
.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étodoObject.getPrototypeOf(obj)
para consultar o protótipo.Reflect.getPrototypeOf(obj)
faz exatamente o mesmo, exceto queReflect
também define um correspondenteReflect.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
eLoader
objeta.Outra explicação é oferecida por este link :
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!
fonte
Reflect.apply
etarget.apply
? Ou o que devo acrescentar antes que a recompensa termine?Object
.Reflect.get
como implementação padrão para proxy get não funciona bem se você estiver fazendo proxy de um objeto com propriedades de protótipo. Ele apenas reclama que não funciona. No entanto, se você usarReflect.get(target, property)
sem passar oreceiver
, ele funcionará.target
é o destino original que o proxy envolve, enquantoreceiver
é o próprio proxy. Mas, novamente, isso pode ser diferente se você conseguir acessar as propriedades de maneira diferente.Indo pelo rascunho do documento encontrado no wiki,
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
Pegamos a linha sobre "objeto comum único" que ela esclarece no rascunho. Ele também contém as definições de função.
O wiki deve ser confiável, pois você pode encontrar um link para ele no site do emcascript
http://www.ecmascript.org/dev.php
No entanto, encontrei o primeiro link do google e não tive sorte em encontrá-lo pesquisando diretamente no wiki.
fonte