Question Comment exécuter une fonction JavaScript lorsque j'ai son nom sous forme de chaîne


J'ai le nom d'une fonction dans JavaScript en tant que chaîne. Comment puis-je convertir cela en un pointeur de fonction pour pouvoir l'appeler plus tard?

Selon les circonstances, il se peut que je doive aussi passer différents arguments dans la méthode.

Certaines fonctions peuvent prendre la forme de namespace.namespace.function(args[...]).


848
2017-12-11 15:47


origine


Réponses:


N'utilisez pas eval sauf si vous absolument, positivement n'a pas d'autre choix.

Comme cela a été mentionné, l'utilisation de quelque chose comme ceci serait la meilleure façon de le faire:

window["functionName"](arguments);

Cela, cependant, ne fonctionnera pas avec une fonction namespace'd:

window["My.Namespace.functionName"](arguments); // fail

Voici comment vous feriez cela:

window["My"]["Namespace"]["functionName"](arguments); // succeeds

Afin de rendre cela plus facile et offrir une certaine flexibilité, voici une fonction pratique:

function executeFunctionByName(functionName, context /*, args */) {
  var args = Array.prototype.slice.call(arguments, 2);
  var namespaces = functionName.split(".");
  var func = namespaces.pop();
  for(var i = 0; i < namespaces.length; i++) {
    context = context[namespaces[i]];
  }
  return context[func].apply(context, args);
}

Vous l'appelleriez comme ça:

executeFunctionByName("My.Namespace.functionName", window, arguments);

Notez que vous pouvez passer dans n'importe quel contexte, donc cela ferait la même chose que ci-dessus:

executeFunctionByName("Namespace.functionName", My, arguments);

1224
2017-12-11 16:15



Je pensais juste que je posterais une version légèrement modifiée de La fonction très utile de Jason Bunting.

D'abord, j'ai simplifié la première déclaration en fournissant un second paramètre tranche(). La version originale fonctionnait bien dans tous les navigateurs sauf IE.

Deuxièmement, j'ai remplacé ce avec le contexte dans la déclaration de retour; autrement, ce pointait toujours vers fenêtre lorsque la fonction cible était en cours d'exécution.

function executeFunctionByName(functionName, context /*, args */) {
    var args = Array.prototype.slice.call(arguments, 2);
    var namespaces = functionName.split(".");
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }
    return context[func].apply(context, args);
}

89
2017-12-04 02:16



La réponse à cette autre question vous montre comment faire cela: L'équivalent Javascript des locaux de Python ()?

Fondamentalement, vous pouvez dire

window["foo"](arg1, arg2);

ou comme d'autres l'ont suggéré, vous pouvez simplement utiliser eval:

eval(fname)(arg1, arg2);

Bien que ce soit extrêmement dangereux, sauf si vous êtes absolument sûr de ce que vous évaluez.


51
2017-12-11 15:49



Ne pourriez-vous pas simplement faire ceci:

var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();

Vous pouvez également exécuter n'importe quel autre JavaScript en utilisant cette méthode.


43
2017-08-16 20:56



Je pense qu'une manière élégante de faire ceci est en définissant vos fonctions dans un objet de hachage. Ensuite, vous pouvez avoir une référence à ces fonctions à partir du hachage en utilisant la chaîne. par exemple.

var customObject = {
  customFunction: function(param){...}
};

Ensuite, vous pouvez appeler:

customObject['customFunction'](param);

Où customFunction sera une chaîne correspondant à une fonction définie dans votre objet.


29
2018-06-02 17:13



Deux choses:

  • évitez eval, c'est terriblement dangereux et lent

  • deuxièmement, peu importe où votre fonction existe, la «globalité» n'est pas pertinente. x.y.foo() peut être activé par x.y['foo']() ou x['y']['foo']() ou même window['x']['y']['foo'](). Vous pouvez enchaîner indéfiniment comme ça.


21
2017-12-11 16:01



Avec ES6, vous pouvez accéder aux méthodes de classe par leur nom:

class X {
  method1(){
    console.log("1");
  }
  method2(){
    this['method1']();
    console.log("2");
  }
}
let x  = new X();
x['method2']();

la sortie serait:

1
2

18
2017-07-08 10:22



Vous avez juste besoin de convertir votre chaîne en un pointeur par window[<method name>]. Exemple:

var function_name = "string";
function_name = window[function_name];

et maintenant vous pouvez l'utiliser comme un pointeur.


12
2017-11-11 18:22



Toutes les réponses supposent que les fonctions peuvent être accédées par l'étendue globale (aka la fenêtre). Cependant, le PO n'a pas fait cette hypothèse.

Si les fonctions résident dans une portée locale (aka fermeture) et ne sont pas référencées par un autre objet local, la malchance: Vous devez utiliser eval () AFAIK, voir appeler dynamiquement la fonction locale en javascript


12
2018-02-04 18:03