Pourquoi l'utilisation de la fonction JavaScript eval est-elle une mauvaise idée?

534

La fonction eval est un moyen puissant et facile de générer dynamiquement du code, alors quelles sont les mises en garde?

Brian Singh
la source
92
Don't be eval () par Simon Willison - 24ways.org/2005/dont-be-eval
Brian Singh
5
Comme indiqué dans moduscreate.com/javascript-performance-tips-tricks - (new Function (str)) () est plus performant que eval (str). Juste mes 2 cents :)
Grgur
3
apparemment nouveau fcuntion (a) est 67% plus lent que eval (a) sur chrome
qu'est
pour moi, les nouvelles fonctions (a) sont 80% plus lentes que le dernier chrome sur osx
john Smith
3
J'ai ajouté une fonction statique, juste pour comparer les performances. jsperf.com/eval-vs-new-function/2
Nepoxx

Réponses:

386
  1. Une mauvaise utilisation d' eval ouvre votre code pour les attaques par injection

  2. Le débogage peut être plus difficile (pas de numéro de ligne, etc.)

  3. le code évalué s'exécute plus lentement (aucune possibilité de compiler / mettre en cache le code évalué)

Edit: Comme le souligne @Jeff Walden dans les commentaires, # 3 est moins vrai aujourd'hui qu'il ne l'était en 2008. Cependant, bien que la mise en cache des scripts compilés puisse se produire, cela ne sera limité qu'aux scripts répétés sans modification. Un scénario plus probable est que vous évaluez des scripts qui ont subi à chaque fois une légère modification et, en tant que tels, ne peuvent pas être mis en cache. Disons simplement que CERTAINS codes évalués s'exécutent plus lentement.

Prestaul
la source
2
@JeffWalden, grand commentaire. J'ai mis à jour mon article bien que je réalise que cela fait un an que vous avez posté. Xnzo72, si vous aviez quelque peu nuancé votre commentaire (comme Jeff l'a fait), je pourrais peut-être être d'accord avec vous. Jeff a souligné la clé: "L'évaluation de la même chaîne plusieurs fois peut éviter la surcharge d'analyse". En l'état, vous avez tout simplement tort; # 3 est vrai pour de nombreux scénarios.
Prestaul
7
@Prestaul: Étant donné que l'attaquant supposé peut simplement utiliser n'importe quel outil de développement pour modifier le JavaScript dans le client, pourquoi dites-vous qu'Eval () ouvre votre code aux attaques par injection? N'est pas déjà ouvert? (Je parle bien sûr du JavaScript client)
Eduardo Molteni
60
@EduardoMolteni, nous ne nous soucions pas (et ne pouvons en effet pas empêcher) les utilisateurs d'exécuter js dans leur propre navigateur. Les attaques que nous essayons d'éviter sont lorsque les valeurs fournies par l'utilisateur sont enregistrées, puis placées plus tard en javascript et évaluées. Par exemple, je peux définir mon nom d'utilisateur sur: badHackerGuy'); doMaliciousThings();et si vous prenez mon nom d'utilisateur, le concattez dans un script et l'évaluez dans les navigateurs d'autres personnes, je peux exécuter le javascript que je veux sur leurs machines (par exemple, les forcer à attribuer +1 à mes messages, publier leurs données sur mon serveur, etc.)
Prestaul
3
En général, # 1 est vrai pour beaucoup, sinon la plupart des appels de fonction. eval () ne doit pas être isolé et évité par les programmeurs expérimentés, simplement parce que les programmeurs inexpérimentés en abusent. Cependant, les programmeurs expérimentés ont souvent une meilleure architecture dans leur code, et eval () sera rarement requis ou même pensé en raison de cette meilleure architecture.
frodeborli
4
@TamilVendhan Bien sûr, vous pouvez mettre des points d'arrêt. Vous pouvez accéder au fichier virtuel créé par Chrome pour votre code évalué en ajoutant la debugger;déclaration à votre code source. Cela arrêtera l'exécution de votre programme sur cette ligne. Ensuite, vous pouvez ajouter des points d'arrêt de débogage comme s'il s'agissait simplement d'un autre fichier JS.
Sid
346

eval n'est pas toujours mauvais. Il y a des moments où c'est parfaitement approprié.

Cependant, eval est actuellement et historiquement massivement sur-utilisé par des gens qui ne savent pas ce qu'ils font. Cela inclut malheureusement des personnes écrivant des didacticiels JavaScript, et dans certains cas, cela peut en effet avoir des conséquences sur la sécurité - ou, plus souvent, de simples bugs. Donc, plus nous pouvons faire pour jeter un point d'interrogation sur eval, mieux c'est. Chaque fois que vous utilisez eval, vous devez vérifier ce que vous faites, car il est probable que vous puissiez le faire de manière plus sûre, meilleure et plus propre.

Pour donner un exemple trop typique, pour définir la couleur d'un élément avec un identifiant stocké dans la variable 'potato':

eval('document.' + potato + '.style.color = "red"');

Si les auteurs du type de code ci-dessus avaient une idée des principes de base du fonctionnement des objets JavaScript, ils se seraient rendu compte que les crochets peuvent être utilisés à la place des noms de points littéraux, évitant ainsi la nécessité d'eval:

document[potato].style.color = 'red';

... qui est beaucoup plus facile à lire et moins potentiellement bogué.

(Mais alors, quelqu'un qui / vraiment / savait ce qu'il faisait disait:

document.getElementById(potato).style.color = 'red';

qui est plus fiable que la vieille astuce douteuse d'accéder aux éléments DOM directement à partir de l'objet document.)

bobince
la source
82
Hmm, je suppose que j'ai eu de la chance quand j'ai appris JavaScript pour la première fois. J'ai toujours utilisé "document.getElementById" pour accéder au DOM; ironiquement, je ne l'ai fait qu'à l'époque parce que je n'avais aucune idée du fonctionnement des objets en JavaScript ;-)
Mike Spross
5
se mettre d'accord. Parfois, l'évaluation est correcte, par exemple pour les réponses JSON des services
Web
40
@schoetbi: Ne devriez-vous pas utiliser à la JSON.parse()place de eval()JSON?
nyuszika7h
4
@bobince code.google.com/p/json-sans-eval fonctionne sur tous les navigateurs, tout comme github.com/douglascrockford/JSON-js . Le json2.js de Doug Crockford utilise eval en interne, mais avec des contrôles. En outre, il est compatible avec la prise en charge intégrée du navigateur pour JSON.
Martijn
8
@bobince Il y a quelque chose appelé détection de fonctionnalités et polyfills pour gérer les bibliothèques JSON manquantes et d'autres choses (regardez modernizr.com )
MauganRa
37

Je pense que c'est parce qu'il peut exécuter n'importe quelle fonction JavaScript à partir d'une chaîne. Son utilisation permet aux utilisateurs d'injecter plus facilement du code non autorisé dans l'application.

kemiller2002
la source
5
Quelle est alors l'alternative?
modernes
5
En réalité, l'alternative est simplement d'écrire du code qui n'en a pas besoin. Crockford va longuement à ce sujet, et si vous avez besoin de l'utiliser, il dit à peu près que c'est un défaut de conception de programme et doit être retravaillé. En vérité, je suis également d'accord avec lui. JS pour tous ses défauts est vraiment flexible, et laisse beaucoup de place pour le rendre flexible.
kemiller2002
3
Ce n'est pas vrai, la plupart des frameworks ont une méthode pour analyser JSON, et si vous n'utilisez pas de framework, vous pouvez utiliser JSON.parse (). La plupart des navigateurs le prennent en charge, et si vous êtes vraiment dans le pétrin, vous pouvez écrire un analyseur pour JSON assez facilement.
kemiller2002
6
Je n'achète pas cet argument, car il est déjà facile d'injecter du code escroc dans une application Javascript. Nous avons des consoles de navigateur, des extensions de script, etc ... Chaque morceau de code envoyé au client est facultatif pour le client à exécuter.
user2867288
6
Le fait est que c'est plus facile pour moi d'injecter du code dans votre navigateur. Supposons que vous utilisez eval sur une chaîne de requête. Si je vous incite à cliquer sur un lien qui mène à ce site avec ma chaîne de requête attachée, j'ai maintenant exécuté mon code sur votre machine avec la permission complète du navigateur. Je veux enregistrer tout ce que vous tapez sur ce site et me l'envoyer? Terminé et aucun moyen de m'arrêter car lorsque eval s'exécute, le navigateur lui donne la plus haute autorité.
kemiller2002
27

Deux points me viennent à l'esprit:

  1. Sécurité (mais tant que vous générez la chaîne à évaluer vous-même, cela peut ne pas être un problème)

  2. Performances: tant que le code à exécuter n'est pas connu, il ne peut pas être optimisé. (sur javascript et les performances, certainement la présentation de Steve Yegge )

xtofl
la source
9
Pourquoi la sécurité est un problème si le client peut de toute façon faire avec notre code tout ce qu'il veut? Mécano ?
Paul Brewczynski
2
@PaulBrewczynski, le problème de sécurité apparaît lorsque l'utilisateur A enregistre sa partie de code pour être mis à jour eval, puis ce petit morceau de code s'exécute sur le navigateur de l'utilisateur B
Felipe Pereira
21

Passer l'entrée utilisateur à eval () est un risque pour la sécurité, mais chaque appel de eval () crée également une nouvelle instance de l'interpréteur JavaScript. Cela peut être un porc de ressources.

Andrew Hedges
la source
27
Depuis plus de 3 ans que je réponds à cette question, ma compréhension de ce qui se passe s'est, disons, approfondie. Ce qui se passe réellement, c'est qu'un nouveau contexte d'exécution est créé. Voir dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts
Andrew Hedges
20

Ce n'est généralement un problème que si vous transmettez une entrée utilisateur eval.

Mark Biek
la source
16

Surtout, c'est beaucoup plus difficile à maintenir et à déboguer. C'est comme un goto. Vous pouvez l'utiliser, mais cela rend plus difficile de trouver des problèmes et plus difficile pour les personnes qui peuvent avoir besoin d'apporter des modifications plus tard.

Brian
la source
Eval peut être utilisé pour remplacer les fonctionnalités de métaprogrammation manquantes, comme les modèles. J'aime bien le générateur compact bien plus qu'une liste interminable de fonctions sur fonctions.
faiblesse du
Tant que la chaîne ne provient pas de l'utilisateur ou est limitée au navigateur que vous pouvez. JavaScript a beaucoup de pouvoir de métaprogrammation en utilisant des choses comme changer les prototypes, obj [membre], Proxy, json.parse, fenêtre, fonctions de décorateur (adverbes) où newf = décorateur (oldf), fonction d'ordre supérieur comme Array.prototype.map (f) , passage d'arguments à d'autres fonctions, arguments de mots clés via {}. Pouvez-vous me dire un cas d'utilisation où vous ne pouvez pas faire cela au lieu de l'évaluation?
aoeu256
13

Une chose à garder à l'esprit est que vous pouvez souvent utiliser eval () pour exécuter du code dans un environnement autrement restreint - les sites de réseaux sociaux qui bloquent des fonctions JavaScript spécifiques peuvent parfois être dupés en les décomposant en un bloc eval -

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

Donc, si vous cherchez à exécuter du code JavaScript où il ne serait pas autorisé autrement ( Myspace , je vous regarde ...), eval () peut être une astuce utile.

Cependant, pour toutes les raisons mentionnées ci-dessus, vous ne devriez pas l'utiliser pour votre propre code, où vous avez un contrôle total - ce n'est tout simplement pas nécessaire, et mieux loti relégué sur le plateau des `` hacks JavaScript délicats ''.

lohkamp mat
la source
1
Il suffit de mettre à jour le code ci-dessus .. --hi là! - doit être entre guillemets car il s'agit d'une chaîne. eval ('al' + 'er' + 't (' + '"hi there!"' + ')');
Mahesh
2
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
Konrad Borowski
4
Oui, il y avait des sites de réseaux sociaux qui restreignaient alert () mais permettaient eval ()?!
joshden
12

À moins que vous ne laissiez eval () un contenu dynamique (via cgi ou entrée), il est aussi sûr et solide que tous les autres JavaScript de votre page.

Thevs
la source
Bien que cela soit vrai - si votre contenu n'est pas dynamique, quelle est la raison d'utiliser eval pour cela? Vous pouvez simplement mettre le code dans une fonction et l'appeler à la place!
Periata Breatta du
Par exemple - pour analyser la valeur de retour (comme JSON, les chaînes définies par le serveur, etc.) provenant de l'appel Ajax.
Thevs
2
Oh je vois. J'appellerais ces dynamiques parce que le client ne sait pas à l'avance ce qu'elles sont, mais je vois ce que vous voulez dire maintenant.
Periata Breatta
7

Avec le reste des réponses, je ne pense pas que les instructions eval puissent avoir une minimisation avancée.

Paul Mendoza
la source
6

C'est un risque de sécurité possible, il a une portée d'exécution différente et est assez inefficace, car il crée un environnement de script entièrement nouveau pour l'exécution du code. Voir ici pour plus d'informations: eval .

Cependant, il est très utile et utilisé avec modération peut ajouter beaucoup de bonnes fonctionnalités.

À M
la source
5

À moins que vous ne soyez sûr à 100% que le code évalué provient d'une source fiable (généralement votre propre application), c'est un moyen infaillible d'exposer votre système à une attaque de script intersite.

John Topley
la source
1
Seulement si votre sécurité côté serveur est nulle. La sécurité côté client est tout simplement absurde.
doubleOrt
5

Je sais que cette discussion est ancienne, mais j'aime vraiment cette approche de Google et je voulais partager ce sentiment avec les autres;)

L'autre chose est que plus vous obtenez mieux, plus vous essayez de comprendre et finalement vous ne croyez pas que quelque chose est bon ou mauvais juste parce que quelqu'un l'a dit :) C'est une vidéo très inspirante qui m'a aidé à réfléchir davantage :) LES BONNES PRATIQUES sont bonnes, mais ne les utilisez pas inconsidérément :)

op1ekun
la source
1
Oui. J'ai trouvé, jusqu'à présent au moins dans Chrome, un cas d'utilisation qui semble être plus efficace. Exécutez un RAF qui évalue une chaîne dans une variable donnée à chaque itération. Utilisez un setInterval pour définir uniquement des éléments à orientation graphique comme la définition de transformations, etc. dans cette chaîne. J'ai essayé de nombreuses autres approches, comme parcourir les fonctions d'un tableau ou utiliser une variable pour définir uniquement des transformations pour les éléments modifiés, mais jusqu'à présent, cela semble être le plus efficace. Quand il s'agit d'animation, le banc d'essai le plus vrai est vos yeux.
jdmayfield
5

Ce n'est pas nécessairement si mauvais à condition de savoir dans quel contexte vous l'utilisez.

Si votre application utilise eval()pour créer un objet à partir d'un JSON qui est revenu d'une requête XMLHttpRequest sur votre propre site, créé par votre code côté serveur de confiance, ce n'est probablement pas un problème.

Le code JavaScript côté client non fiable ne peut pas faire grand-chose de toute façon. À condition que la chose sur laquelle vous exécutez eval()provienne d'une source raisonnable, tout va bien.

MarkR
la source
3
N'est-ce pas plus lent d'utiliser eval que de simplement analyser le JSON?
Brendan Long
@Qix - l'exécution de ce test sur mon navigateur (Chrome 53) montre que l' évaluation est un peu plus rapide que l' analyse .
Periata Breatta du
@PeriataBreatta Huh, étrange. Je me demande pourquoi. À l'époque, j'ai dit que ce n'était pas le cas. Cependant, il n'est pas rare que Chrome obtienne d'étranges améliorations des performances dans certaines zones de l'exécution d'une version à l'autre.
Qix - MONICA A ÉTÉ MAUVAISE
Un petit vieux fil ici, mais d'après ce que j'ai lu - sans prétendre l'avoir retracé moi-même - JSON.parse en fait, il est entré dans la phase finale. Donc, en termes d'efficacité, cela demande plus de travail / temps. Mais pour la sécurité, pourquoi ne pas simplement analyser? eval est un outil génial. Utilisez-le pour des choses qui n'ont pas d'autre moyen. Pour passer des fonctions via JSON, il existe un moyen de le faire sans eval. Ce deuxième paramètre dans JSON.stringify vous permet de mettre un rappel à exécuter que vous pouvez vérifier via typeof s'il s'agit d'une fonction. Récupérez ensuite le .toString () de la fonction. Il y a de bons articles à ce sujet si vous recherchez.
jdmayfield
4

Cela réduit considérablement votre niveau de confiance en matière de sécurité.

David Plumpton
la source
4

Si vous voulez que l'utilisateur entre des fonctions logiques et évalue ET ET OU alors la fonction d'évaluation JavaScript est parfaite. Je peux accepter deux chaînes et eval(uate) string1 === string2, etc.

Ian
la source
Vous pouvez également utiliser Function () {}, mais soyez prudent lorsque vous les utilisez sur le serveur, sauf si vous voulez que les utilisateurs prennent le contrôle de votre serveur hahahah.
aoeu256
3

Si vous repérez l'utilisation de eval () dans votre code, souvenez-vous du mantra «eval () est mauvais».

Cette fonction prend une chaîne arbitraire et l'exécute en tant que code JavaScript. Lorsque le code en question est connu à l'avance (non déterminé lors de l'exécution), il n'y a aucune raison d'utiliser eval (). Si le code est généré dynamiquement lors de l'exécution, il existe souvent un meilleur moyen d'atteindre l'objectif sans eval (). Par exemple, l'utilisation de la notation entre crochets pour accéder aux propriétés dynamiques est meilleure et plus simple:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

En utilisant eval() également des implications sur la sécurité, car vous pouvez exécuter du code (par exemple provenant du réseau) qui a été falsifié. Il s'agit d'un antipattern commun lorsqu'il s'agit d'une réponse JSON à partir d'une demande Ajax. Dans ces cas, il est préférable d'utiliser les méthodes intégrées des navigateurs pour analyser la réponse JSON pour vous assurer qu'elle est sûre et valide. Pour les navigateurs qui ne prennent pas en charge JSON.parse()nativement, vous pouvez utiliser une bibliothèque de JSON.org.

Il est également important de se rappeler que le passage de chaînes à setInterval(), setTimeout()et le Function()constructeur est, pour la plupart, similaire à l'utilisationeval() et doit donc être évité.

Dans les coulisses, JavaScript doit encore évaluer et exécuter la chaîne que vous passez en tant que code de programmation:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

L'utilisation du nouveau constructeur Function () est similaire à eval () et doit être abordée avec précaution. Ce pourrait être une construction puissante mais est souvent mal utilisée. Si vous devez absolument utilisereval() , vous pouvez plutôt utiliser new Function ().

Il y a un petit avantage potentiel car le code évalué dans new Function () s'exécutera dans une étendue de fonction locale, donc toutes les variables définies avec var dans le code évalué ne deviendront pas globalement automatiquement.

Une autre façon d'empêcher les globaux automatiques consiste à encapsuler l' eval()appel dans une fonction immédiate.

12345678
la source
Pouvez-vous suggérer comment évaluer un nom de variable dynamique de fonction locale sans eval? Les fonctions Eval (et similaires) sont des derniers recours dans la plupart des langues qui les contiennent, mais parfois c'est nécessaire. Dans le cas de l'obtention du nom d'une variable dynamique, une solution est-elle plus sûre? Dans tous les cas, le javascript lui-même n'est pas pour une réelle sécurité (côté serveur est évidemment la principale défense). Si vous êtes intéressé, voici mon cas d'utilisation d'eval, que j'aimerais changer: stackoverflow.com/a/48294208
Regular Joe
2

Outre les problèmes de sécurité possibles si vous exécutez du code soumis par l'utilisateur, la plupart du temps, il existe un meilleur moyen qui n'implique pas une nouvelle analyse du code à chaque exécution. Les fonctions anonymes ou les propriétés d'objet peuvent remplacer la plupart des utilisations d'eval et sont beaucoup plus sûres et plus rapides.

Matthew Crumley
la source
2

Cela peut devenir plus problématique à mesure que la prochaine génération de navigateurs sortira avec une certaine saveur d'un compilateur JavaScript. Le code exécuté via Eval peut ne pas fonctionner aussi bien que le reste de votre JavaScript contre ces nouveaux navigateurs. Quelqu'un devrait faire du profilage.

Brian
la source
2

C'est l'un des bons articles qui parlent d'eval et comment ce n'est pas un mal: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

Je ne dis pas que vous devriez vous épuiser et commencer à utiliser eval () partout. En fait, il existe très peu de bons cas d'utilisation pour exécuter eval (). Il y a certainement des problèmes de clarté de code, de débogage et certainement de performances qui ne doivent pas être négligés. Mais vous ne devriez pas avoir peur de l'utiliser lorsque vous avez un cas où eval () a du sens. Essayez de ne pas l'utiliser d'abord, mais ne laissez personne vous faire peur en pensant que votre code est plus fragile ou moins sécurisé lorsque eval () est utilisé de manière appropriée.

Amr Elgarhy
la source
2

eval () est très puissant et peut être utilisé pour exécuter une instruction JS ou évaluer une expression. Mais la question ne concerne pas les utilisations de eval () mais permet simplement de dire comment la chaîne que vous exécutez avec eval () est affectée par une partie malveillante. À la fin, vous exécuterez du code malveillant. Le pouvoir s'accompagne d'une grande responsabilité. Donc, utilisez-le judicieusement si vous l'utilisez. Ce n'est pas beaucoup lié à la fonction eval () mais cet article contient de très bonnes informations: http://blogs.popart.com/2009/07/javascript-injection-attacks/ Si vous recherchez les bases de eval () regardez ici: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

Phi
la source
2

Le moteur JavaScript dispose d'un certain nombre d'optimisations de performances qu'il effectue pendant la phase de compilation. Certains d'entre eux se résument à être en mesure d'analyser essentiellement statiquement le code pendant qu'il lexe, et de prédéterminer où se trouvent toutes les déclarations de variables et de fonctions, de sorte qu'il faut moins d'efforts pour résoudre les identificateurs pendant l'exécution.

Mais si le moteur trouve un eval (..) dans le code, il doit essentiellement supposer que toute sa connaissance de l'emplacement de l'identifiant peut être invalide, car il ne peut pas savoir au moment de lexing exactement quel code vous pouvez passer à eval (..) pour modifier la portée lexicale ou le contenu de l'objet vers lequel vous pouvez passer pour créer une nouvelle portée lexicale à consulter.

En d'autres termes, au sens pessimiste, la plupart de ces optimisations qu'il ferait sont inutiles si eval (..) est présent, il n'effectue donc tout simplement pas les optimisations.

Cela explique tout.

Référence :

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

hkasera
la source
Aucun moteur javascript ne peut trouver et évaluer dans le code avec une garantie de 100%. Par conséquent, il doit être prêt à tout moment.
Jack Giffin
2

Ce n'est pas toujours une mauvaise idée. Prenons par exemple la génération de code. J'ai récemment écrit une bibliothèque appelée Hyperbars qui comble le fossé entre virtual-dom et guidon . Pour ce faire, il analyse un modèle de guidon et le convertit en hyperscript qui est ensuite utilisé par virtual-dom. L'hyperscript est d'abord généré sous forme de chaîne et avant de le renvoyer, eval()il le transforme en code exécutable. j'ai trouvéeval() dans cette situation particulière l'opposé exact du mal.

Fondamentalement de

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

Pour ça

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

La performance de eval() ne sont pas un problème dans une situation comme celle-ci, car vous n'avez besoin d'interpréter la chaîne générée qu'une seule fois, puis de réutiliser la sortie exécutable plusieurs fois.

Vous pouvez voir comment la génération de code a été réalisée si vous êtes curieux ici .

Wikened
la source
2

J'irais jusqu'à dire que cela n'a pas vraiment d'importance si vous utilisez eval()en javascript qui est exécuté dans les navigateurs. * (Mise en garde)

Tous les navigateurs modernes ont une console de développeur où vous pouvez de toute façon exécuter du javascript arbitraire et tout développeur semi-intelligent peut regarder votre source JS et mettre tout ce dont il a besoin dans la console de développement pour faire ce qu'il souhaite.

* Tant que vos points de terminaison de serveur ont la validation et la désinfection correctes des valeurs fournies par l'utilisateur, peu importe ce qui est analysé et évalué dans votre javascript côté client.

eval()Cependant, si vous demandez s'il est approprié d'utiliser en PHP, la réponse est NON , à moins que vous ne mettiez en liste blanche les valeurs qui peuvent être transmises à votre instruction eval.

Adam Copley
la source
non seulement il y a une console de développement, vous pouvez également taper du code javascript: dans la barre d'url pour créer votre propre console de développement sur la page s'il n'y en a pas, comme c'est le cas sur les anciens navigateurs IE et les appareils mobiles.
Dmitry
1

Je n'essaierai pas de réfuter ce qui a été dit jusqu'ici, mais je proposerai cette utilisation d'eval () qui (pour autant que je sache) ne peut être faite autrement. Il y a probablement d'autres façons de coder cela, et probablement des façons de l'optimiser, mais cela se fait à la main et sans cloches et sifflets pour plus de clarté afin d'illustrer une utilisation d'eval qui n'a vraiment pas d'autre alternative. C'est-à-dire: des noms d'objets créés par programmation dynamiques (ou plus précisément) (par opposition aux valeurs).

//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
        if(i === 0){
            namespaceToTest = namespaceParts[i];
        }
        else{
            namespaceToTest = namespaceToTest + "." + namespaceParts[i];
        }

        if(eval('typeof ' + namespaceToTest) === "undefined"){
            eval(namespaceToTest + ' = {}');
        }
    }
    return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
    //Code goes here
    //this.MyOtherMethod("foo"));  // => "foo"
    return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

EDIT: au fait, je ne suggérerais pas (pour toutes les raisons de sécurité mentionnées ci-dessus) que vous basiez vos noms d'objet sur les entrées utilisateur. Je ne peux cependant imaginer aucune bonne raison pour laquelle vous voudriez faire cela. Pourtant, j'ai pensé que je ferais remarquer que ce ne serait pas une bonne idée :)

Carnix
la source
3
cela peut être fait avec namespaceToTest[namespaceParts[i]], pas besoin d'évaluation ici, donc if(typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {};la seule différence pour leelse namespaceToTest = namespaceToTest[namespaceParts[i]];
user2144406
1

Collecte des ordures

La récupération de place des navigateurs n'a aucune idée si le code qui est évalué peut être supprimé de la mémoire, il le conserve donc jusqu'à ce que la page soit rechargée. Pas trop mal si vos utilisateurs ne sont que brièvement sur votre page, mais cela peut être un problème pour les webapps.

Voici un script pour démontrer le problème

https://jsfiddle.net/CynderRnAsh/qux1osnw/

document.getElementById("evalLeak").onclick = (e) => {
  for(let x = 0; x < 100; x++) {
    eval(x.toString());
  }
};

Quelque chose d'aussi simple que le code ci-dessus entraîne le stockage d'une petite quantité de mémoire jusqu'à la fin de l'application. C'est pire quand le script évalué est une fonction géante, et appelé intervalle.

JD
la source