O método eval é uma função global do JavaScript que permite executar código representado como uma string. Embora forneça capacidades poderosas de execução dinâmica, seu uso deve ser limitado devido a implicações de segurança e desempenho. Em situações específicas, pode ser utilizado para alterar dinamicamente o escopo de execução do código, oferecendo maior flexibilidade.
Valores, Expressões e Instruções Dinâmicas
console.log(typeof eval('true')); // boolean
console.log(typeof eval("'9'")); // string
console.log(typeof eval('8')); // number
Pontos importantes:
- Quando o código contém uma expressão,
evala calcula e retorna seu valor.
console.log(eval('1+1')); // 2
- Quando o código contém uma ou mais instruções JavaScript,
evalas executa.
console.log(eval('1+1')); // 2
console.log(eval('8')); // expressão de valor único
console.log(eval('8;')); // instrução de valor único
// Diferenças semânticas são tratadas pelo analisador léxico do JavaScript
- Desde o ECMAScript 3, existem restrições para prevenir uso indevido. Não é possível atribuir
evala outra variável para chamada flexível, nem sobrescrever a propriedadeeval.
// Em ES3:
let funcaoEval = eval;
console.log(funcaoEval('8')); // Erro de EvalError
// Atualmente:
let funcaoEval = eval;
console.log(funcaoEval('8+9')); // 17
- Se a última instrução possuir um valor de retorno,
evalo retorna. - Se o código não retornar valor,
evalretornaundefined. Em JavaScript, exceto instruções vazias ou de controle, a maioria das instruções produz um valer determinado pela última sub-instrução ou expressão.
let codigo = "for (let i = 0; i < 50; i++) { console.log(i); }";
// Executa e imprime valores de 0 a 49
console.log(eval(codigo)); // undefined – eval retorna o valor da execução, ou undefined se não houver
- Se o código lançar uma exceção,
evala propaga ao chamador.
try {
let codigo = "for (let i = 0; i < 50; i++) { ; }";
console.log(eval(codigo)); // undefined
} catch (erro) {
console.log(erro.message); // Mensagem de erro
}
- A maioria das funções JavaScript converte parâmetros para string antes de processamento, mas
evalé especial: se o parâmetrocodenão for uma string primitiva,evalo retorna sem processamento. Ao passar strings primitivas, evite objetos String.
let objString = new String('1+2'); // Objeto String
console.log(eval(objString)); // Retorna a string "1+2"
let stringPrimitiva = "1+2"; // Literal de string primitiva
console.log(eval(stringPrimitiva)); // 3
console.log(typeof eval(stringPrimitiva)); // number
Ambiguidades em Literais de Objetos e Funções
O método eval executa expressões e instruções comuns, retornando seus valores, mas certos códigos podem gerar ambiguidades e erros.
var objeto = '{usuario:"c88",senha:"123456"}';
console.log(eval(objeto)); // Lança erro
Ambiguidades ocorrem devido a estruturas compostas e ao uso de dois-pontos. Para evitar isso, encapsule o objeto em parênteses:
var objeto = '({usuario:"c88",senha:"123456"})';
console.log(eval(objeto)); // {usuario: 'c88', senha: '123456'}
Funções, enquanto expressões de objeto, também requerem tratamento semelhante para evitar ambiguidades:
var funcaoCodificada = "(function(){ return 8 })()";
console.log(eval(funcaoCodificada)); // 8
var funcaoCodificada = "(function(){ return 8 }())";
console.log(eval(funcaoCodificada)); // 8
// Alternativa menos recomendada:
var funcaoCodificada = "function(){ return 8 }";
console.log(eval("(" + funcaoCodificada + "())")); // 8
Arrays não apresentam esse problema e podem ser usados diretamente:
var arrayCodificado = '["abc","xyz"][0]';
console.log(eval(arrayCodificado)); // "abc"
Escopo de Execução Global e Compatibilidade
O escopo de execução refere-se ao ambiente onde o código JavaScript roda – global ou local. Para código dinamicamente executado via eval, a questão do escopo se torna cmoplexa.
var x = 1; // Global
function teste() {
var x = 3;
eval('x = 5'); // Afeta escopo local
// Para modificar a variável global:
window.eval('x = 5'); // Altera escopo global
console.log(x); // 5 (local)
}
teste();
console.log(x); // 1 (global)
Escopo de Execução Atual
Conforme observado, eval no escopo global afeta apenas variáveis com o mesmo nome no mesmo nível. Dentro de funções, altera apenas variáveis do escopo local, mantendo isolamento entre domínios interno e externo.
eval("var y = 1");
function teste() {
eval("var y = 2");
console.log(y); // 2
}
teste();
console.log(y); // 1