Método eval em JavaScript: Guia para Execução Dinâmica de Código

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, eval a calcula e retorna seu valor.
console.log(eval('1+1')); // 2

  • Quando o código contém uma ou mais instruções JavaScript, eval as 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 eval a outra variável para chamada flexível, nem sobrescrever a propriedade eval.
// 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, eval o retorna.
  • Se o código não retornar valor, eval retorna undefined. 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, eval a 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âmetro code não for uma string primitiva, eval o 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

Tags: javascript eval execução-dinâmica escopos segurança-web

Publicado em 5-29 15:13 por Thomas