web-dev-qa-db-fra.com

Eval () et new Function () sont-ils la même chose?

Ces deux fonctions font-elles la même chose dans les coulisses? (dans les fonctions d'instructions uniques)

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'));
83
qwertymk

Non, ce ne sont pas les mêmes.

  • eval() évalue une chaîne en tant qu'expression JavaScript dans la portée d'exécution actuelle et peut accéder aux variables locales.
  • new Function() analyse le code JavaScript stocké dans une chaîne dans un objet fonction, qui peut ensuite être appelé. Il ne peut pas accéder aux variables locales car le code s'exécute dans une étendue distincte.

Considérez ce code:

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

Si new Function('return (a = 22);')() était utilisé, la variable locale a conserverait sa valeur. Néanmoins, certains programmeurs JavaScript tels que Douglas Crockford pensent que aucun ne doit être utilisé sauf absolument nécessaire , et l'évaluation/l'utilisation du constructeur Function sur des données non fiables n'est pas sécurisée et imprudent.

107
PleaseStand

Non.

Dans votre mise à jour, les appels à evaluate et func produisent le même résultat. Mais ils ne font certainement pas "la même chose en coulisses". La fonction func crée une nouvelle fonction, mais l'exécute immédiatement, tandis que la fonction evaluate exécute simplement le code sur place.

De la question d'origine:

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

Cela vous donnera des résultats très différents:

evaluate('0) + (4');
func('0) + (4');
6
palswim

new Function crée une fonction qui peut être réutilisée. eval exécute simplement la chaîne donnée et retourne le résultat de la dernière instruction. Votre question est erronée lorsque vous avez tenté de créer une fonction wrapper qui utilise Function pour émuler un eval.

Est-il vrai qu'ils partagent du code derrière les rideaux? Oui, très probablement. Exactement le même code? Non, certainement.

Pour le plaisir, voici ma propre implémentation imparfaite en utilisant eval pour créer une fonction. J'espère que cela fait la lumière sur la différence!

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 plus grande différence entre cette fonction et la nouvelle fonction est qu'elle n'a pas de portée lexicale. Il n'aurait donc pas accès aux variables de fermeture et le mien le serait.

6
Juan Mendes

Si vous voulez dire, cela donnera-t-il les mêmes résultats, alors oui ... mais juste pour évaluer (aka, "évaluer cette chaîne de JavaScript") serait beaucoup plus simple.

MODIFIER Ci-dessous:

C'est comme dire ... ces deux problèmes mathématiques sont-ils les mêmes:

1 + 1

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

2
Timothy Khouri

Dans cet exemple, les résultats sont les mêmes, oui. Les deux exécutent l'expression que vous passez. C'est ce qui les rend si dangereux.

Mais ils font des choses différentes derrière l'odeur. Celui impliquant new Function(), en arrière-plan, crée une fonction anonyme à partir du code que vous fournissez, qui est exécutée lorsque la fonction est invoquée.

Le JavaScript que vous lui transmettez n'est techniquement pas exécuté tant que vous n'avez pas appelé la fonction anonyme. Cela contraste avec eval() qui exécute le code immédiatement et ne génère pas de fonction basée sur lui.

1
Chris Laplante

Je veux juste souligner une syntaxe utilisée dans les exemples ici et ce que cela signifie:

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

notez que la fonction (...) () a le "()" à la fin. Cette syntaxe obligera func à exécuter la nouvelle fonction et à renvoyer la chaîne et non une fonction qui renvoie une chaîne, mais si vous utilisez ce qui suit:

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

Maintenant, func renverra une fonction qui retourne une chaîne.

1
Jack D Menendez