Temos o produto (aplicativo de desktop normal) que deseja extrair alguns dados dos produtos Adobe (dos documentos abertos nesses produtos). Como os eventos da Apple são muito lentos, implementamos uma interoperabilidade personalizada que envia jsx gerado (Adobe ActionScript3 baseado no JavaScript 1.5, não há muito extinto) para processos de produtos da Adobe via soquete. Isso é mais de 2.000 vezes mais rápido do que usar eventos, mas nos obriga a fazer alguns truques envolvendo eval
, sendo que o objetivo atual é minimizar os riscos de corromper inadvertidamente o estado do mecanismo JSX pelo eval
.
Esse código é executado em um ambiente confiável (não no navegador) e o código em si também é confiável, portanto, quaisquer considerações de segurança eval
não são aplicáveis. O principal objetivo da questão é evitar a poluição de âmbito global realizada pelo eval
.
Ao usar o eval
, o resultado da última expressão é considerado como o valor de retorno do todo eval
, por exemplo, o resultado do eval
-ing do código a seguir será o valor da y+2=12
expressão.
var res = eval("
var x = 5;
var y = x*2;
y+2;
"); //res = 12
Ao mesmo tempo, se envolvermos esse código no Function
construtor, o resultado seráundefined
var res = (new Function("
var x = 5;
var y = x*2;
y+2;
")).call(); //res=undefined
Para corrigir o último trecho, precisamos adicionar um retorno explícito à última expressão:
var res = (new Function("
var x = 5;
var y = x*2;
return y+2; // <------- changes here
")).call(); //res=12
Portanto, eval
e Function
têm semânticas de retorno diferentes.
E não posso simplesmente substituir eval
pelo Function()
código legado. Também serei forçado a alterar o lado da chamada para adicionar return
no código, passado para Function()
.
Existe uma maneira de evitar a adição de retorno explícito, para que seja possível substituir eval
pelo Function()
de forma transparente (suponhamos que não estamos interessados no acesso ao escopo local)?
Ou talvez exista outra técnica que possa fornecer o equivalente ao eval
que minimizará os riscos da poluição de escopo global e fornecerá a mesma semântica de retorno do original eval
?
Basta retornar o código avaliado da função:
Ou como Mike sugeriu:
Observe que, para correção técnica, o bloco inicial
eval
que você está mostrando não resulta apenas em 12, resulta em tudo o que você escreveu =)eval
é uma macro que interrompe a execução JS, substitui o código que você fornece, executa-o e, em seguida, retoma a execução normal. Então neste caso o resultado são duas variáveis novasx
ey
no mesmo escopo queeval
foi executado, e o "12" simplesmente vem do fato de que as atribuições estão retornando operações.Se você não quiser introduzir nada de novo em seu escopo, lembre-se de que
eval
é uma macro: coloque-a no código que você precisa:(Ou use a solução de Alexander onde você cria uma função "real" com the
eval
como corpo da função)E, claro, isso também pode aceitar argumentos:
Isso agora executará um IIFE que faz tudo o que precisa, retorna 12 e, em seguida, coleta o lixo.
Mas é claro, e esta é a parte importante: se é isso que você precisa, então não precisa avaliar nada. Você pode simplesmente escrever a função e chamá-la com os valores que você já possui. Você quase nunca precisa do
eval
, mesmo em scripts da Adobe.