我有一个JavaScript函数的名称作为字符串。如何将其转换为函数指针以便稍后调用?

根据具体情况,我可能还需要将各种参数传递到方法中。

一些函数可以采用namespace.namespace.function(args[…])的形式。


当前回答

不要使用eval,除非你绝对没有其他选择。

如前所述,使用这样的东西是最好的方法:

window["functionName"](arguments);

然而,这对命名空间函数不起作用:

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

你可以这样做:

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

为了让这更容易,并提供一些灵活性,这里有一个便利函数:

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);
}

你可以这样称呼它:

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

注意,你可以在任何你想要的上下文中传递,所以这将和上面一样:

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

其他回答

小心! !

在JavaScript中应该尽量避免通过字符串调用函数,原因有两个:

原因1:一些代码混淆器会破坏你的代码,因为它们会改变函数名,使字符串无效。

原因2:维护使用这种方法的代码要困难得多,因为定位字符串调用的方法的用法要困难得多。

您所要做的就是使用上下文或定义函数驻留的新上下文。 你不局限于window["f"]();

下面是我如何为一些REST服务使用一些动态调用的示例。

/* 
Author: Hugo Reyes
@ www.teamsrunner.com

*/

    (function ( W, D) { // enclose it as self invoking function to avoid name collisions.


    // to call function1 as string
    // initialize your FunctionHUB as your namespace - context
    // you can use W["functionX"](), if you want to call a function at the window scope.
    var container = new FunctionHUB();


    // call a function1 by name with one parameter.

    container["function1"](' Hugo ');


    // call a function2 by name.
    container["function2"](' Hugo Leon');


    // OO style class
    function FunctionHUB() {

        this.function1 = function (name) {

            console.log('Hi ' + name + ' inside function 1')
        }

        this.function2 = function (name) {

            console.log('Hi' + name + ' inside function 2 ')
        }
    }

})(window, document); // in case you need window context inside your namespace.

如果你想从一个字符串生成整个函数,那是另一个答案。 另外请注意,你不局限于一个单一的命名空间,如果你的命名空间存在于my.name.space.for.functions.etc.etc.etc,那么你的命名空间的最后一个分支包含了my.name.space.for.functions.etc.etc["function"]();

希望能有所帮助。 H。

我认为一种优雅的方法是在哈希对象中定义函数。然后,您可以使用字符串从哈希中引用这些函数。如。

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

然后你可以调用:

customObject['customFunction'](param);

其中customFunction将是一个匹配对象中定义的函数的字符串。

更新

这个答案似乎对许多程序员有帮助,所以这里有一个更新版本。

在ES6中,你还可以使用计算属性名,这将允许你避免魔法字符串。

const FunctionNames = Object.freeze({ FirstFunction:“FirstFunction”, SecondFunction:“SecondFunction” }); … var customObject = { [functionname。FirstFunction]:函数(参数){…} [functionname。SecondFunction]:函数(参数){…} }; … customObject [FunctionNames.FirstFunction](参数);

所有答案都假设函数可以通过全局作用域(窗口)访问。然而,OP并没有做出这样的假设。

如果函数存在于局部作用域(即闭包)中,并且没有被其他局部对象引用,那么运气就不好了:你必须使用eval() AFAIK,参见 在javascript中动态调用局部函数

所以,就像其他人说的,最好的选择是:

window['myfunction'](arguments)

就像Jason Bunting说的,如果你的函数名包含一个对象,它就不会工作:

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

下面是我的函数版本,它将按名称执行所有函数(包括对象与否):

My = { 代码:{ 是:{ Nice:函数(a, b){警报(a + "," + b);} } } }; Guy = function(){alert('awesome');} 函数executeFunctionByName(str, args) { Var arr = str.split('.'); Var fn = window[arr[0]]; For (var I = 1;I < arrr .length;我+ +) {fn = fn[arr[i]];} fn。应用(窗口,args); } executeFunctionByName(“my.code.is。Nice ', ['arg1', 'arg2']); executeFunctionByName(“家伙”);