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

1051

J'ai le nom d'une fonction en JavaScript sous forme de chaîne. Comment convertir cela en un pointeur de fonction pour pouvoir l'appeler plus tard?

Selon les circonstances, je devrai peut-être également passer divers arguments dans la méthode.

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

Kieron
la source

Réponses:

1440

N'utilisez pas evalsauf si vous n'avez absolument aucun autre choix.

Comme cela a été mentionné, l'utilisation de quelque chose comme ça 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 procéder:

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

Afin de faciliter cela et d'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'appeleriez ainsi:

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

Remarque, vous pouvez passer dans le contexte que vous voulez, donc cela ferait la même chose que ci-dessus:

executeFunctionByName("Namespace.functionName", My, arguments);
Jason Bunting
la source
4
vous savez que vous n'avez pas besoin de toute la construction "func"? "context.apply" seul est très bien
annakata
16
Bien sûr, je le sais - mais la façon dont j'ai écrit la fonction apporte une certaine clarté à ceux qui la lisent qui ne comprennent pas complètement ce qui se passe. J'ai écrit cette fonction en réalisant que les gens qui le lisent peuvent avoir besoin d'aide. Je vais cependant vous fournir un remplaçant, puisque vous avez demandé ...
Jason Bunting
108
Grattez cela - le code est suffisamment clair et ceux qui le savent le savent. Si vous êtes comme moi et que vous savez ce que vous faites, vous pouvez simplement apporter ces modifications par vous-même si vous avez utilisé ce code. Stack Overflow est destiné à éduquer les autres, et je pense que mon code est plus facile à comprendre pour le novice. Merci quand même!
Jason Bunting
4
Y a-t-il une situation où la fenêtre ["funcName"] retournerait indéfinie? C'est le problème que je rencontre en ce moment. Le code appelant et la fonction sont définis dans deux fichiers js distincts. J'ai essayé de les ajouter au même fichier mais cela n'a fait aucune différence.
codemonkey
5
Je pense qu'il y a un problème ici. Lorsque vous appelez My.Namespace.functionName(), thisfera référence à l' My.Namespaceobjet. Mais lorsque vous appelez executeFunctionByName("My.Namespace.functionName", window), il n'y a aucun moyen de faire thisréférence à la même chose. Il devrait peut-être utiliser le dernier espace de noms comme étendue, ou windows'il n'y a pas d'espaces de noms. Ou vous pouvez autoriser l'utilisateur à spécifier la portée comme argument.
JW.
100

Je pensais juste publier une version légèrement modifiée de la fonction très utile de Jason Bunting .

Tout d'abord, j'ai simplifié la première instruction en fournissant un deuxième paramètre à slice () . La version originale fonctionnait bien dans tous les navigateurs sauf IE.

Deuxièmement, j'ai remplacé cela par le contexte dans la déclaration de retour; sinon, cela pointait toujours vers la fenêtre lors de l'exécution de la fonction cible.

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);
}
Alex Nazarov
la source
Il n'y a pas de vérification pour voir si "functionName" existe réellement?
Crashalot
Je pense que la réponse de Mac est sous-estimée. Je ne suis pas un expert mais il semble bien pensé et robuste.
Martin Hansen Lennox
65

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

En gros, vous pouvez dire

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

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

eval(fname)(arg1, arg2);

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

Eli Courtwright
la source
6
la première forme est de loin préférable
annakata
19
N'utilisez eval qu'en dernier recours, lorsque tout le reste échoue.
Jason Bunting
1
C'est ... mais cela fonctionnera-t-il avec des fonctions comme celle-ci: xyz (args)?
Kieron
@keiron: oui. voir ma réponse ci
annakata
55

Ne pourriez-vous pas simplement faire ceci:

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

Vous pouvez également exécuter tout autre JavaScript à l'aide de cette méthode.

Lieu noir
la source
3
fonctionne lorsque même des arguments sont passés avec la fonction
adeel41
Qu'en est-il du retour de fonction?
Peter Denev
12
En quoi est-ce différent de eval("My.Namespace.functionName()");?
developerbmw
@PeterDenev vient de changer la première ligne envar codeToExecute = "return My.Namespace.functionName()";
developerbmw
2
@developerbmw, voici la réponse stackoverflow.com/questions/4599857/…
Tejasvi Hegde
48

Je pense qu'une façon élégante de le faire est de définir 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.

Ruben Daddario
la source
@ibsenv, merci de votre commentaire pour m'aider à identifier cette réponse comme la meilleure. J'ai créé un tableau d'objets de fonction et utilisé à mon tour pour créer un tableau de deferred.promises. J'ai mis un exemple de code ci-dessous. (Je ne voulais pas créer de nouvelle réponse et emprunter la réponse de Ruben.)
user216661
fonction getMyData (arrayOfObjectsWithIds) {var functionArray = arrayOfObjectsWithIds.map (function (value) {return {myGetDataFunction: MyService.getMyData (value.id)};}) var promises = functionArray.map (function (getDataFunction) {var deferred = $ q.defer (); getDataFunction.myGetDataFunction.success (function (data) {deferred.resolve (data)}). error (function (error) {deferred.reject ();}); return deferred.promise;}); return $ q.all (promesses) .then (function (dataArray) {// faire des trucs})};
user216661
Cela fonctionne très bien, je n'ajoute que le trait de soulignement / lodash pour vérifier si c'est une fonction. Et puis exécutez
elporfirio
35

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

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

la sortie serait:

1
2
nils petersohn
la source
1
Meilleur javascript PURE ... Dieu .. supprimer la classe ne fonctionne pas et mais c'est ok. Merci!
KingRider
1
C'est la chose que je cherchais depuis longtemps. Merci!
PaladiN
ES2015 n'a rien à voir ici. Vous pouvez atteindre le même objectif à l'aide d'objets purs ou d'une délégation de prototype via Object.create(). const myObj = {method1 () {console.log ('1')}, method2 () {console.log ('2')}} myObj ['method1'] (); // 1 myObj ['méthode2'] (); // 2
sminutoli
1
C'est de l'or !!! Je suis surpris de n'avoir jamais pensé à cela auparavant. Agréable!!!
thxmike
Je pense aussi que c'est la meilleure façon d'atteindre notre objectif.
Chris Jung
24

Deux choses:

  • éviter l'eval, c'est terriblement dangereux et lent

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

annakata
la source
1
mais vous ne pouvez pas faire window ['xyz'] () pour appeler xyz ()
nickf
17

Toutes les réponses supposent que les fonctions sont accessibles via une portée globale (fenêtre). Cependant, le PO n'a pas fait cette hypothèse.

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

Wolfgang Kuehn
la source
2
Mec (ou dudette), merci beaucoup de l'avoir signalé! Je pensais que je devenais fou pendant une seconde.
Funktr0n
13

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

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

et maintenant vous pouvez l'utiliser comme un pointeur.

Amirali
la source
Cela semble être un moyen beaucoup plus sûr.
James Poulose
12

Voici ma contribution aux excellentes réponses de Jason Bunting / Alex Nazarov, où j'inclus la vérification des erreurs demandée par Crashalot.

Compte tenu de ce préambule (artificiel):

a = function( args ) {
    console.log( 'global func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] );
    }
};
ns = {};
ns.a = function( args ) {
    console.log( 'namespace func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] ); 
    }
};
name = 'nsa';
n_s_a = [ 'Snowden' ];
noSuchAgency = function(){};

puis la fonction suivante:

function executeFunctionByName( functionName, context /*, args */ ) {
    var args, namespaces, func;

    if( typeof functionName === 'undefined' ) { throw 'function name not specified'; }

    if( typeof eval( functionName ) !== 'function' ) { throw functionName + ' is not a function'; }

    if( typeof context !== 'undefined' ) { 
        if( typeof context === 'object' && context instanceof Array === false ) { 
            if( typeof context[ functionName ] !== 'function' ) {
                throw context + '.' + functionName + ' is not a function';
            }
            args = Array.prototype.slice.call( arguments, 2 );

        } else {
            args = Array.prototype.slice.call( arguments, 1 );
            context = window;
        }

    } else {
        context = window;
    }

    namespaces = functionName.split( "." );
    func = namespaces.pop();

    for( var i = 0; i < namespaces.length; i++ ) {
        context = context[ namespaces[ i ] ];
    }

    return context[ func ].apply( context, args );
}

vous permettra d'appeler une fonction javascript par nom stocké dans une chaîne, à espace de noms ou globale, avec ou sans arguments (y compris les objets Array), fournissant des commentaires sur toutes les erreurs rencontrées (en espérant les attraper).

L'exemple de sortie montre comment cela fonctionne:

// calling a global function without parms
executeFunctionByName( 'a' );
  /* OUTPUT:
  global func passed:
  */

// calling a global function passing a number (with implicit window context)
executeFunctionByName( 'a', 123 );
  /* OUTPUT:
  global func passed:
  -> 123
  */

// calling a namespaced function without parms
executeFunctionByName( 'ns.a' );
  /* OUTPUT:
  namespace func passed:
  */

// calling a namespaced function passing a string literal
executeFunctionByName( 'ns.a', 'No Such Agency!' );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  */

// calling a namespaced function, with explicit context as separate arg, passing a string literal and array 
executeFunctionByName( 'a', ns, 'No Such Agency!', [ 007, 'is the man' ] );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  -> 7,is the man
  */

// calling a global function passing a string variable (with implicit window context)
executeFunctionByName( 'a', name );
  /* OUTPUT:
  global func passed:
  -> nsa
  */

// calling a non-existing function via string literal
executeFunctionByName( 'n_s_a' );
  /* OUTPUT:
  Uncaught n_s_a is not a function
  */

// calling a non-existing function by string variable
executeFunctionByName( n_s_a );
  /* OUTPUT:
  Uncaught Snowden is not a function
  */

// calling an existing function with the wrong namespace reference
executeFunctionByName( 'a', {} );
  /* OUTPUT:
  Uncaught [object Object].a is not a function
  */

// calling no function
executeFunctionByName();
  /* OUTPUT:
  Uncaught function name not specified
  */

// calling by empty string
executeFunctionByName( '' );
  /* OUTPUT:
  Uncaught  is not a function
  */

// calling an existing global function with a namespace reference
executeFunctionByName( 'noSuchAgency', ns );
  /* OUTPUT:
  Uncaught [object Object].noSuchAgency is not a function
  */
Mac
la source
Je sais pas ... c'est un très bon effort, c'est clair. Mais ça me semble "trop ​​large" ...
TechNyquist
2
Hein? SO est une plateforme de questions / réponses / d'enseignement. Je fournirai avec plaisir tous les exemples auxquels je peux penser pour transmettre, espérons-le, un éclairage. Pour moi, c'est le point .
Mac
Si vous évaluez le functionName de toute façon, pourquoi ne pas simplement l'utiliser?
données du
Ça ne marche pas pour moi. J'ai une fonction d'espacement de noms abcd où d est le nom de la fonction. l'appel executeFunctionByName ("abcd", fenêtre) échoue en ligne qui vérifie if( typeof context[ functionName ] !== 'function' )parce que le contexte - fenêtre - est défini, est un objet et un tableau, mais la fenêtre ['abcd'] n'existe pas car elle a été identifiée comme un problème dans l'accepté réponse: window["My.Namespace.functionName"](arguments); // fail
akousmata
12

Selon l'endroit où vous vous trouvez, vous pouvez également utiliser:

this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();

ou, dans nodejs

global["funcname"]()
Zibri
la source
9

Si vous souhaitez appeler une fonction d'un objet au lieu d'une fonction globale avec window["functionName"]. Vous pouvez le faire comme;

var myObject=new Object();
myObject["functionName"](arguments);

Exemple:

var now=new Date();
now["getFullYear"]()
Ahmet DAL
la source
8

FAITES ATTENTION!!!

Il faut essayer d'éviter d'appeler une fonction par chaîne en JavaScript pour deux raisons:

Raison 1: certains obfuscateurs de code vont détruire votre code car ils changeront les noms de fonction, rendant la chaîne invalide.

Raison 2: Il est beaucoup plus difficile de maintenir le code qui utilise cette méthodologie car il est beaucoup plus difficile de localiser les utilisations des méthodes appelées par une chaîne.

dykstrad
la source
7

Voici mon approche Es6 qui vous permet d'appeler votre fonction par son nom en tant que chaîne ou son nom de fonction et vous permet également de passer différents nombres d'arguments à différents types de fonctions:

function fnCall(fn, ...args)
{
  let func = (typeof fn =="string")?window[fn]:fn;
  if (typeof func == "function") func(...args);
  else throw new Error(`${fn} is Not a function!`);
}


function example1(arg1){console.log(arg1)}
function example2(arg1, arg2){console.log(arg1 + "  and   " + arg2)}
function example3(){console.log("No arguments!")}

fnCall("example1", "test_1");
fnCall("example2", "test_2", "test3");
fnCall(example3);
fnCall("example4"); // should raise an error in console

pouyan
la source
6

Surpris de ne voir aucune mention de setTimeout.

Pour exécuter une fonction sans arguments:

var functionWithoutArguments = function(){
    console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);

Pour exécuter la fonction avec des arguments:

var functionWithArguments = function(arg1, arg2) {
    console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");

Pour exécuter une fonction à espace de noms profond:

var _very = {
    _deeply: {
        _defined: {
            _function: function(num1, num2) {
                console.log("Execution _very _deeply _defined _function : ", num1, num2);
            }
        }
    }
}
setTimeout("_very._deeply._defined._function(40,50)", 0);
abhishekisnot
la source
Cela ne fournit pas de réponse à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous son article - vous pouvez toujours commenter vos propres articles, et une fois que vous aurez une réputation suffisante, vous pourrez commenter n'importe quel article .
AstroCB
Veuillez ajouter un exemple de la façon dont vous appelleriez runMeavec quelques arguments.
lexicore
1
@lexicore J'ai voté pour la suppression dans une file d'attente de révision, car elle ne fournit pas clairement une réponse substantielle à la question et elle est de peu de valeur en soi.
AstroCB
1
Cette méthode a un défaut potentiellement énorme, car elle met l'exécution à la fin de la file d'attente de rendu , rendant ainsi cet appel asynchrone
PeterM
1
J'aime cette réponse, elle semble fonctionner pour mes besoins.
Quintonn
3

Ainsi, comme d'autres l'ont dit, la meilleure option est certainement:

window['myfunction'](arguments)

Et comme Jason Bunting l'a dit , cela ne fonctionnera pas si le nom de votre fonction inclut un objet:

window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work

Voici donc ma version d'une fonction qui exécutera toutes les fonctions par leur nom (y compris un objet ou non):

my = {
    code : {
        is : {
            nice : function(a, b){ alert(a + "," + b); }
        }
    }
};

guy = function(){ alert('awesome'); }

function executeFunctionByName(str, args)
{
    var arr = str.split('.');
    var fn = window[ arr[0] ];
    
    for (var i = 1; i < arr.length; i++)
    { fn = fn[ arr[i] ]; }
    fn.apply(window, args);
}

executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']);
executeFunctionByName('guy');

pmrotule
la source
3
  let t0 = () => { alert('red0') }
  var t1 = () =>{ alert('red1') }
  var t2 = () =>{ alert('red2') }
  var t3 = () =>{ alert('red3') }
  var t4 = () =>{ alert('red4') }
  var t5 = () =>{ alert('red5') }
  var t6 = () =>{ alert('red6') }

  function getSelection(type) {
    var evalSelection = {
      'title0': t0,
      'title1': t1,
      'title2': t2,
      'title3': t3,
      'title4': t4,
      'title5': t5,
      'title6': t6,
      'default': function() {
        return 'Default';
      }
    };
    return (evalSelection[type] || evalSelection['default'])();
  }
  getSelection('title1');

Une solution plus POO ...

Leo Lanese
la source
2

Un détail supplémentaire sur les publications de Jason et Alex. J'ai trouvé utile d'ajouter une valeur par défaut au contexte. Mettez juste context = context == undefined? window:context;au début de la fonction. Vous pouvez changer windowquel que soit votre contexte préféré, puis vous n'aurez pas besoin de passer la même variable chaque fois que vous l'appelez dans votre contexte par défaut.

Bradley Shrader
la source
2

Pour ajouter à la réponse de Jason Bunting, si vous utilisez nodejs ou quelque chose (et cela fonctionne aussi dans dom js), vous pouvez utiliser à la thisplace de window(et rappelez-vous: eval is evil :

this['fun'+'ctionName']();
Cilan
la source
2

Il y a une chose très similaire dans mon code. J'ai une chaîne générée par le serveur qui contient un nom de fonction que je dois passer comme rappel pour une bibliothèque tierce. J'ai donc un code qui prend la chaîne et retourne un "pointeur" sur la fonction, ou null s'il n'est pas trouvé.

Ma solution était très similaire à " la fonction très utile de Jason Bunting " * , bien qu'elle ne s'exécute pas automatiquement et que le contexte soit toujours sur la fenêtre. Mais cela peut être facilement modifié.

J'espère que cela sera utile à quelqu'un.

/**
 * Converts a string containing a function or object method name to a function pointer.
 * @param  string   func
 * @return function
 */
function getFuncFromString(func) {
    // if already a function, return
    if (typeof func === 'function') return func;

    // if string, try to find function or method of object (of "obj.func" format)
    if (typeof func === 'string') {
        if (!func.length) return null;
        var target = window;
        var func = func.split('.');
        while (func.length) {
            var ns = func.shift();
            if (typeof target[ns] === 'undefined') return null;
            target = target[ns];
        }
        if (typeof target === 'function') return target;
    }

    // return null if could not parse
    return null;
}
Nomaed
la source
1

Je ne peux pas résister à mentionner une autre astuce, ce qui aide si vous avez un nombre inconnu d'arguments qui sont également passés dans le cadre de la chaîne contenant le nom de la fonction. Par exemple:

var annoyingstring = 'call_my_func(123, true, "blah")';

Si votre Javascript fonctionne sur une page HTML, tout ce dont vous avez besoin est un lien invisible; vous pouvez passer une chaîne dans l' onclickattribut et appeler la clickméthode.

<a href="#" id="link_secret"><!-- invisible --></a>

$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();

Ou créez l' <a>élément au moment de l'exécution.

Magnus Smith
la source
Solution créative, mais cela ne fonctionnera pas pour les arguments de type objet ou tableau.
Dennis Heiden
1
Cela utilise eval sous le capot ... Et vraiment tourner autour du pot pour le faire
Juan Mendes
1

Le moyen le plus simple est d'y accéder comme un élément

window.ClientSideValidations.forms.location_form

est identique à

window.ClientSideValidations.forms['location_form']
crazycrv
la source
1

Vous pouvez appeler la fonction javascript dans l'un eval("functionname as string")ou l' autre. Comme ci-dessous: (eval est une fonction javascript pure)

function testfunc(){
    return "hello world";
}

$( document ).ready(function() {

     $("div").html(eval("testfunc"));
});

Exemple de travail: https://jsfiddle.net/suatatan/24ms0fna/4/

Suat Atan PhD
la source
Cela fonctionne bien et c'est si simple
Carlos E
1
Et aussi très lent.
Marco
1

Cela fonctionne pour moi:

var command = "Add";
var tempFunction = new Function("Arg1","Arg2", "window." + command + "(Arg1,Arg2)");
tempFunction(x,y);

J'espère que cela fonctionne.

DevAshish
la source
1

Je ne pense pas que vous ayez besoin de fonctions intermédiaires ou d'évaluation complexes ou que vous dépendiez de variables globales comme la fenêtre:

function fun1(arg) {
  console.log(arg);
}

function fun2(arg) {
  console.log(arg);
}

const operations = {
  fun1,
  fun2
};

let temp = "fun1";

try {
  // You have to use square brackets property access
  operations["fun1"]("Hello World");
  operations["fun2"]("Hello World");
  // You can use variables
  operations[temp]("Hello World");
} catch (error) {
  console.error(error);
}

Il fonctionnera également avec les fonctions importées:

// mode.js
export function fun1(arg) {
  console.log(arg);
}

export function fun2(arg) {
  console.log(arg);
}
// index.js
import { fun1, fun2 } from "./mod";

const operations = {
  fun1,
  fun2
};

try {
  operations["fun1"]("Hello World");
  operations["fun2"]("Hello World");
} catch (error) {
  console.error(error);
}
SnnSnn
la source
0

Sans utiliser, eval('function()')vous pourriez créer une nouvelle fonction en utilisant new Function(strName). Le code ci-dessous a été testé à l'aide de FF, Chrome, IE.

<html>
<body>
<button onclick="test()">Try it</button>
</body>
</html>
<script type="text/javascript">

  function test() {
    try {    
        var fnName = "myFunction()";
        var fn = new Function(fnName);
        fn();
      } catch (err) {
        console.log("error:"+err.message);
      }
  }

  function myFunction() {
    console.log('Executing myFunction()');
  }

</script>
Ithar
la source
0
use this

function executeFunctionByName(functionName, context /*, args */) {
      var args = [].slice.call(arguments).splice(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);
    }
Pratik
la source
1
Pourquoi? Les réponses sans explication sont probablement inutiles.
Daniel W.
0

Regardez basique:

var namefunction = 'jspure'; // String

function jspure(msg1 = '', msg2 = '') { 
  console.log(msg1+(msg2!=''?'/'+msg2:''));
} // multiple argument

// Results ur test
window[namefunction]('hello','hello again'); // something...
eval[namefunction] = 'hello'; // use string or something, but its eval just one argument and not exist multiple

Existe une autre fonction de type est la classe et regarde l'exemple nils petersohn

KingRider
la source
0

Merci pour la réponse très utile. J'utilise la fonction de Jason Bunting dans mes projets.

Je l'ai étendu pour l'utiliser avec un délai d'attente facultatif, car la façon normale de définir un délai d'attente ne fonctionnera pas. Voir la question de abhishekisnot

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

var _very = {
    _deeply: {
        _defined: {
            _function: function(num1, num2) {
                console.log("Execution _very _deeply _defined _function : ", num1, num2);
            }
        }
    }
}

console.log('now wait')
executeFunctionByName("_very._deeply._defined._function", window, 2000, 40, 50 );

Néo
la source