40 votes

Utilisations légitimes du constructeur de fonctions

Comme dit à plusieurs reprises, il est considéré comme une mauvaise pratique d'utiliser la Fonction de constructeur (voir aussi la Spécification du Langage ECMAScript, 5ème édition, § 15.3.2.1):

new Function ([arg1[, arg2[, … argN]],] functionBody)

(où tous les arguments sont des chaînes de caractères contenant les noms d'argument et le dernier (ou le seul) chaîne de caractères contient le corps de la fonction).

Pour récapituler, on dit que c'est lent, comme l'a expliqué l'équipe Opera:

Chaque fois [...] l' Function le constructeur est appelé sur une chaîne représentant le code source, le script le moteur doit démarrer la machine qui convertit le code source à l'exécutable code. C'est généralement coûteux pour la performance facilement une centaine de fois plus cher qu'une simple fonction l'appel, par exemple. (Marque "Tarquin' Wilton-Jones)

Si ce n'est pas que mauvais, en fonction de ce post sur MCM (je n'ai pas testé moi-même à l'aide de la version actuelle de Firefox, tout de même).

Crockford ajoute que

[t]il, citant les conventions de l' la langue, il est très difficile de exprimer correctement un corps de la fonction en tant que chaîne de caractères. Dans la forme d'une chaîne, au début de la vérification d'erreur ne peut pas être fait. [...] Et c'est un gaspillage de mémoire, parce que chaque la fonction exige de ses propres indépendant la mise en œuvre.

Une autre différence est que

une fonction définie par une Fonction constructeur de ne pas hériter de toute la portée autre que la portée globale (qui tous fonctions hériter). (MDC)

En dehors de cela, vous devez être attentif afin d'éviter l'injection de code malveillant, lorsque vous créez un new Function à l'aide du contenu dynamique.

Cela dit, T. J. Crowder dit dans une réponse que

[t]voici presque jamais besoin de le semblable [...] la nouvelle Fonction(...), soit, encore une fois, sauf pour les quelques avancées des cas limites.

Alors, maintenant, je me demande: quels sont ces "pointe de cas"? Sont là utilisations légitimes de la Fonction constructeur?

19voto

kangax Points 19954

NWMatcher - Javascript sélecteur CSS et matcher, par Diego Perini - utilise Function constructeur (1, 2, 3, 4, etc.) pour créer ("compiler"), hautement efficace, les versions de sélecteur de rapprochement.

L' indice de référence (dont je viens de tomber sur Chrome 5) parle de lui-même:

alt text

Notez la différence entre NWMatcher et Grésillement, qui est très similaire sélecteur de moteur, seulement sans la fonction de compilation :)

Sur une note de côté, ECMAScript 5 ne jette pas les erreurs sur l'invocation de la Function. Ni dans la plus stricte, ni dans la "norme" des modes. Le mode Strict, cependant, introduit peu de restrictions sur la présence de signes distinctifs tels que "eval" et "arguments":

  • Vous ne pouvez pas déclarer des variables/fonctions/arguments avec des noms tels:

    function eval() { }
    var eval = { };
    function f(eval) { } 
    var o = { set f(eval){ } };
    
  • Vous ne pouvez pas attribuer à ces identificateur:

    eval = { };
    

Notez également qu'en mode strict, eval de la sémantique est légèrement différente de celle dans l'ES3. Le mode Strict code ne peut pas instancier des variables ou des fonctions dans l'environnement à partir de laquelle il a été appelé:

 eval(' "use strict"; var x = 1; ');
 typeof x; // "undefined"

9voto

harpo Points 17399

jQuery l'utilise pour analyser les chaînes JSON lorsqu'un objet analyseur JSON n'est pas disponible. Cela me semble légitime :)

         // Try to use the native JSON parser first
        return window.JSON && window.JSON.parse ?
            window.JSON.parse( data ) :
            (new Function("return " + data))();
 

7voto

David Titarenco Points 17148

J'utilise l' new Function() constructeur comme une ligne en-JS interprète dans l'un des web apps je suis en développement:

function interpret(s) {
  //eval(s); <-- even worse practice
  try {
      var f = new Function(s);
      f();
    }
  catch (err) {
      //graceful error handling in the case of malformed code
  }
}

Comme je l'ai avoir des trucs en streaming sur AJAX (pas un iframe), j'ai continuellement interpret() sur readyStateChange == 3. Cela fonctionne étonnamment bien.

Edit: voici un cas d'étude qui montre que, new Function() n'est absolument plus rapide que l' eval(). I. e. vous ne devriez jamais (rarement?) utiliser la fonction eval en lieu et place de l' new Function().

http://polyfx.com/stuff/bsort.html <- les 1000 de l'itération de la version, peut faire planter votre navigateur

http://polyfx.com/stuff/bsort10.html <- la version la plus courte

Eval est, en moyenne, près de 8 fois plus lent que l' new Function().

7voto

Prestaul Points 31986

John Resig a utilisé le constructeur Function pour créer des versions "compilées" de modèles côté client écrits avec une syntaxe asp. http://ejohn.org/blog/javascript-micro-templating/

3voto

harpo Points 17399

C'est un cas distinct à partir de mon autre réponse.

J'ai utilisé la Fonction constructeur a tout à l'arrière pour créer de chaîne personnalisée des formateurs qui ont été appelés à plusieurs reprises. La surcharge de la création de la fonction (qui, pour moi, c'est le problème de performances dont vous parlez) a été largement compensé par l'amélioration du rendement de la mesure intégré des fonctions, qui ont été créés lors de l'exécution spécifiquement pour traiter un format de chaîne de caractères, et donc n'a pas besoin d'évaluer des tonnes de pertinence des cas — ou analyser une chaîne de format, pour cette question. C'est un peu comme la compilation d'une expression régulière, je suppose.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X