eval()

La méthode eval() permet d'évaluer du code JavaScript représenté sous forme d'une chaîne de caractères.

Syntaxe

eval(str)

Paramètres

str
Une chaîne de caractères qui représente une expression JavaScript ou une instruction ou une suite d'instructions JavaScript. L'expression utilisée peut contenir des variables et des propriétés d'objets existants.

Description

eval() est une fonction rattachée à l'objet global.

eval() prend en compte un argument qui est une chaîne de caractères. Si cette chaîne représente une expression, eval() évaluera l'expression. Si l'argument utilisé représente une ou plusieurs instructions JavaScript, eval() évaluera les instructions. eval() ne doit pas être utilisé pour évaluer une expression arithmétique. En effet, JavaScript évalue automatiquement les expressions arithmétiques.

Si on construit une expression arithmétique sous la forme d'une chaîne de caractères, on peut utiliser eval() pour évaluer cette expression par la suite. Ainsi, si on a une variable x, on peut préparer une expression à utiliser plus tard en construisant la chaîne "3 * x + 2" par exemple. Au moment où on souhaite procéder à l'évaluation, on appellera eval() avec cette chaîne de caractères.

Si l'argument passé à eval() n'est pas une chaîne de caractères, eval() renverra l'argument inchangé. Dans l'exemple qui suit, on utilise le constructeur String, eval() renvoie donc un objet String au lieu d'évaluer la chaîne de caractères correspondante.

eval(new String("2 + 2")); // renvoie un objet String contenant "2 + 2"
eval("2 + 2");             // renvoie 4

Ce comportement peut être résolu de façon générique en utilisant la méthode toString().

var expression = new String("2 + 2");
eval(expression.toString());

La fonction eval ne peut pas être utilisée indirectement avec un autre nom. Toute tentative d'un tel appel doit provoquer une erreur d'exécution. Ainsi, il ne devrait pas être possible d'utiliser le code suivant :

var x = 2;
var y = 4;
var monÉval = eval;
monÉval("x + y");

N'utiliser eval() qu'en dernier recours !

eval() est une fonction dangereuse qui exécute le code passé en argument avec les privilèges de l'environnement appelant. Si eval() est utilisée avec une chaîne construite de façon mal intentionnée, cela pourra entraîner l'exécution d'un code malveillant sur la machine de l'utilisateur avec les permissions données au site ou au module complémentaire. À un niveau encore plus critique, du code tiers pourrait ainsi consulter la portée dans laquelle eval() a été invoquée. Cela peut permettre des attaques qui n'auraient pas été rendues possible en utilisant un objet Function.

eval() est également plus lente que les méthodes alternatives. En effet, l'évaluation nécessite de faire appel à l'interpréteur JavaScript alors que de nombreuses structures sont optimisées par les moteurs JavaScript modernes.

Dans de nombreux cas, il existe des alternatives plus sûres et plus performantes à eval().

Accéder aux propriétés d'un objet

eval() ne doit pas être utilisée pour convertir des noms de propriétés en propriétés. Par exemple, lorsqu'on ne sait pas quelle propriété va être consultée avant l'exécution, on pourrait utiliser :

var obj = { a: 20, b: 30 };
var nomPropriété = getNomProp();  //une méthode qui renvoie "a" ou "b"

eval( "var résultat = obj." + nomPropriété );

Cependant, eval() n'est pas du tout nécessaire. Il est beaucoup plus simple, plus sécurisé, plus rapide, d'utiliser les accesseurs de propriétés :

var obj = { a: 20, b: 30 };
var nomPropriété = getNomProp();  // une méthode qui renvoie  "a" or "b"
var résultat = obj[nomPropriété]; //  obj[ "a" ] correspond à obj.a 

Utiliser des fonctions au lieu de morceaux de code

Les fonctions JavaScript sont des citoyens de premier rang du langage, cela signifie que les fonctions peuvent être passées comme arguments aux autres API, qu'elles peuvent être stockées dans des variables, dans des propriétés d'objets, etc. De nombreuses API pour le DOM fonctionnent en prenant en argument des fonctions :

// au lieu de setTimeout(" ... ", 1000) on utilisera :
setTimeout(function() { ... }, 1000); 

// au lieu de elt.setAttribute("onclick", "...") on utilisera :
elt.addEventListener("click", function() { ... } , false); 

Les fermetures (closures) sont utiles lorsqu'on souhaite obtenir des fonctions paramétrées sans avoir à concaténer des chaînes de caractères.

Convertir des chaînes JSON en objets JavaScript (parsing)

Si la chaîne utilisée avec eval() contient des données (par exemple, un tableau : "[1, 2, 3]") et non du code, il est conseillé d'utiliser du JSON, qui permet de représenter un sous-ensemble des données représentables en JavaScript.

On notera que la syntaxe JSON est limitée relativement à la syntaxe JavaScript. De nombreux littéraux JavaScript ne pourront être parsés en JSON (par exemple, les virgules à la fin des instructions ne seront pas autorisées et les noms de propriétés devront être compris entre simples quotes). Il est souvent préférable d'utiliser un outil de sérialisation JSON pour que les chaînes générées puissent être analysée en JSON.

Transmettre des données et non du code

Si on a par exemple une extension conçue pour parcourir le code d'une page web, on pourra transmettre des données XPath au lieu d'un code JavaScript.

Exécuter du code avec des privilèges restreints

S'il faut nécessairement exécuter du code, il faut le faire avec des privilèges restreints. Cela s'applique généralement aux modules complémentaires ou aux applications XUL. Pour cela, on pourra utiliser Components.utils.evalInSandbox.

Exemples

Utiliser eval()

Dans le code suivant, les deux instructions passées à eval() sous la forme d'une chaîne renvoient 42. La première évaluation porte sur la chaîne "x + y + 1" ; la seconde évaluation porte sur la chaîne de caractères "42".

var x = 2;
var y = 39;
var z = "42";
eval("x + y + 1"); // renvoie 42
eval(z);           // renvoie 42 

Utiliser eval() pour une chaîne d'instructions

Dans l'exemple qui suit, eval() est utilisée pour évaluer la chaîne de caractères str. Cette chaîne contient plusieurs instructions JavaScript qui affichent un message dans la console et qui affectent la valeur 42 à la variable z si x vaut cinq et 0 sinon. Lorsque la seconde instruction est exécutée, eval() entraînera l'exécution des instructions, les instructions seront évaluées et la valeur de z sera donc renvoyée.

var x = 5;
var str = "if (x == 5) {console.log('z vaut 42'); z = 42;} else z = 0; ";
console.log("z vaut "+eval(str));

Le résultat d'eval() est celui de la dernière expression

eval() renvoie la valeur de la dernière expression évaluée :

var str = "if ( a ) { 1+1; } else { 1+2; }";
var a = true;
var b = eval(str);  // renvoie 2
 
console.log("b vaut : " + b);

a = false;
b = eval(str);      // renvoie 3

console.log("b vaut : " + b);

eval() et les fonctions

Pour qu'une fonction soit restituée lors de l'évaluation, il est nécessaire d'encadrer l'expression contenue dans la chaîne de caractères avec des parenthèses :

var fctStr1 = "function a() {}"
var fctStr2 = "(function a() {})"
var fct1 = eval(fctStr1)  // renvoie undefined
var fct2 = eval(fctStr2)  // renvoie une function

Spécifications

Spécification Statut Commentaires
Première édition d'ECMAScript. Standard Définition initiale.
ECMAScript 5.1 (ECMA-262)
La définition de 'eval' dans cette spécification.
Standard  
ECMAScript 6 (ECMA-262)
La définition de 'eval' dans cette spécification.
En cours de validation comme recommandation  

Compatibilité des navigateurs

Fonctionnalité Chrome Firefox (Gecko) Internet Explorer Opera Safari
Support simple (Oui) (Oui) (Oui) (Oui) (Oui)
Fonctionnalité Android Chrome pour Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Support simple (Oui) (Oui) (Oui) (Oui) (Oui) (Oui)

Notes spécifiques à Gecko

  • Historiquement, eval() utilisait un deuxième argument qui définissait l'objet qui était le contexte pour lequel effectuer l'évaluation. Cet argument était non-standard et a été retiré de SpiderMonkey avec  Gecko 1.9.1 (Firefox 3.5). Pour plus d'informations, voir bug 442333.

Voir aussi

Étiquettes et contributeurs liés au document

Étiquettes : 
Contributeurs à cette page : SphinxKnight, teoli, Jeremie, Tiller, Mgjbot, BenoitL
Dernière mise à jour par : SphinxKnight,
Masquer la barre latérale