Réponses:
J'ai ajouté un test jsperf pour 4 façons différentes de créer une fonction à partir d'une chaîne:
Utilisation de RegExp avec la classe Function
var func = "function (a, b) { return a + b; }".parseFunction();
Utilisation de la classe Function avec "return"
var func = new Function("return " + "function (a, b) { return a + b; }")();
Utilisation du constructeur de fonctions officiel
var func = new Function("a", "b", "return a + b;");
Utiliser Eval
eval("var func = function (a, b) { return a + b; };");
Une meilleure façon de créer une fonction à partir d'une chaîne est d'utiliser Function
:
var fn = Function("alert('hello there')");
fn();
Cela a pour avantage / désavantage que les variables de la portée actuelle (si ce n'est globale) ne s'appliquent pas à la fonction nouvellement construite.
Passer des arguments est également possible:
var addition = Function("a", "b", "return a + b;");
alert(addition(5, 3)); // shows '8'
Function
vous ne polluez pas la portée locale et c'est pourquoi cela eval
rend l'optimisation si difficile pour les moteurs ... Avec l'exemple OP, je voudrais:var fnc = Function('return '+s)();
element.onclick = function() { alert("test"); }
.
Vous êtes assez proche.
//Create string representation of function
var s = "function test(){ alert(1); }";
//"Register" the function
eval(s);
//Call the function
test();
Voici un violon qui fonctionne .
eval
Avertissement obligatoire aux futurs chercheurs: eval
peut ouvrir des failles pour les pirates: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... mais si vous connaissez ses dangers et pouvez les éviter, alors c'est un bon moyen simple de créer une fonction à partir d'une chaîne
Oui, l'utilisation Function
est une excellente solution mais nous pouvons aller un peu plus loin et préparer un analyseur universel qui analyse la chaîne et la convertit en véritable fonction JavaScript ...
if (typeof String.prototype.parseFunction != 'function') {
String.prototype.parseFunction = function () {
var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
var match = funcReg.exec(this.replace(/\n/g, ' '));
if(match) {
return new Function(match[1].split(','), match[2]);
}
return null;
};
}
exemples d'utilisation:
var func = 'function (a, b) { return a + b; }'.parseFunction();
alert(func(3,4));
func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
func();
voici jsfiddle
JavaScript
Function
var name = "foo";
// Implement it
var func = new Function("return function " + name + "(){ alert('hi there!'); };")();
// Test it
func();
// Next is TRUE
func.name === 'foo'
Source: http://marcosc.com/2012/03/dynamic-function-names-in-javascript/
eval
var name = "foo";
// Implement it
eval("function " + name + "() { alert('Foo'); };");
// Test it
foo();
// Next is TRUE
foo.name === 'foo'
sjsClass
https://github.com/reduardo7/sjsClass
Class.extend('newClassName', {
__constructor: function() {
// ...
}
});
var x = new newClassName();
// Next is TRUE
newClassName.name === 'newClassName'
Cette technique peut être finalement équivalente à la méthode eval, mais je voulais l'ajouter, car elle pourrait être utile pour certains.
var newCode = document.createElement("script");
newCode.text = "function newFun( a, b ) { return a + b; }";
document.body.appendChild( newCode );
C'est fonctionnellement comme ajouter cet élément <script> à la fin de votre document, par exemple:
...
<script type="text/javascript">
function newFun( a, b ) { return a + b; }
</script>
</body>
</html>
Utilisez le new Function()
avec un retour à l'intérieur et exécutez-le immédiatement.
var s = `function test(){
alert(1);
}`;
var new_fn = new Function("return " + s)()
console.log(new_fn)
new_fn()
Un exemple avec des arguments dynamiques:
let args = {a:1, b:2}
, fnString = 'return a + b;';
let fn = Function.apply(Function, Object.keys(args).concat(fnString));
let result = fn.apply(fn, Object.keys(args).map(key=>args[key]))