¿Eval() y new Function () son lo mismo?


¿Estas dos funciones están haciendo lo mismo entre bastidores? (en funciones de instrucción simple)

var evaluate = function(string) {
    return eval('(' + string + ')');
}

var func = function(string) {
    return (new Function( 'return (' + string + ')' )());
}

console.log(evaluate('2 + 1'));
console.log(func('2 + 1'));
Author: Lucky Kleinschmidt, 2011-01-05

7 answers

No, son no lo mismo.

  • eval() evalúa una cadena como una expresión JavaScript dentro del ámbito de ejecución actual y puede acceder a variables locales.
  • new Function() analiza el código JavaScript almacenado en una cadena en un objeto de función, que luego se puede llamar. No puede acceder a variables locales porque el código se ejecuta en un ámbito separado.

Considere este código:

function test1() {
    var a = 11;
    eval('(a = 22)');
    alert(a);            // alerts 22
}

Si new Function('return (a = 22);')(), la variable local a conservaría su valor. Sin embargo, algunos programadores de JavaScript como Douglas Crockford creen que no se debe usar a menos que sea absolutamente necesario, y evaluar/usar el constructor Function en datos no confiables es inseguro e imprudente.

 91
Author: PleaseStand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:30

No.

En su actualización, las llamadas a evaluate y func producen el mismo resultado. Pero, definitivamente no están "haciendo lo mismo entre bastidores". La función func crea una nueva función, pero luego la ejecuta inmediatamente, mientras que la función evaluate simplemente ejecuta el código en el acto.

De la pregunta original:

var evaluate = function(string) {
    return eval(string);
}
var func = function(string) {
    return (new Function( 'return (' + string + ')' )());
}

Estos te darán resultados muy diferentes:

evaluate('0) + (4');
func('0) + (4');
 6
Author: palswim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 00:56:30

new Function crea una función que se puede reutilizar. eval simplemente ejecuta la cadena dada y devuelve el resultado de la última instrucción. Su pregunta está equivocada cuando intentó crear una función de envoltura que usa la función para emular una evaluación.

¿Es cierto que comparten algún código detrás de las cortinas? Sí, es muy probable. Exactamente el mismo código? No, desde luego.

Por diversión, aquí está mi propia implementación imperfecta usando eval para crear una función. Espero que arroje algo de luz en el la diferencia!

function makeFunction() {
  var params = [];
  for (var i = 0; i < arguments.length -  1; i++) {
    params.push(arguments[i]);
  }
  var code = arguments[arguments.length -  1];


 // Creates the anonymous function to be returned
 // The following line doesn't work in IE
 // return eval('(function (' + params.join(',')+ '){' + code + '})');
 // This does though
 return eval('[function (' + params.join(',')+ '){' + code + '}][0]');
}

La mayor diferencia entre esta Función y la nueva es que la Función no tiene un ámbito léxico. Así que no tendría acceso a las variables de cierre y la mía sí.

 6
Author: Juan Mendes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-24 17:13:35

Si quieres decir, dará los mismos resultados, entonces sí... pero solo para evaluar (también conocido como, "evaluar esta cadena de JavaScript") sería mucho más simple.

EDITAR a continuación:

Es como decir... son estos dos problemas matemáticos los mismos:

1 + 1

1 + 1 + 1 - 1 + 1 - 1 * 1 / 1

 2
Author: Timothy Khouri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 00:40:25

En ese ejemplo, los resultados son los mismos, sí. Ambos ejecutan la expresión que pasa. Esto es lo que los hace tan peligrosos.

Pero hacen cosas diferentes detrás de la escena. El que involucra new Function(), detrás de las escenas, crea una función anónima a partir del código que usted suministra, que se ejecuta cuando se invoca la función.

El JavaScript que se le pasa técnicamente no se ejecuta hasta que invoca la función anónima. Esto está en contraste con eval() que ejecuta el código de inmediato, y no genera una función basada en él.

 1
Author: Chris Laplante,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 00:40:06

Solo quiero señalar alguna sintaxis utilizada en los ejemplos aquí y lo que significa:

 var func = function(string) {
     return (new Function( 'return (' + string + ')' )());
 }

Observe que la Función(...) () tiene el "() " al final. Esta sintaxis hará que func ejecute la nueva función y devuelva la cadena no una función que devuelva la cadena, pero si usa lo siguiente:

 var func = function(string) {
     return (new Function( 'return (' + string + ')' ));
 }

Ahora func devolverá una función que devuelve una cadena.

 1
Author: Jack D Menendez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-13 17:40:55

La función tiene un alcance de ejecución diferente con el llamante, eval tiene el mismo. Pero esta regla solo es válida antes de ES6, en ES6 y future, eval tienen el mismo comportamiento con la función.

 -2
Author: Mr Code,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-02 12:15:47