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

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

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


当前回答

惊讶地看到没有提到setTimeout。

运行一个不带参数的函数:

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

运行带参数的函数:

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

运行深度命名空间函数:

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

其他回答

  const myFnCollection = {
    myFnStringName: function(args) {}
  };

  let fn = 'myFnStringName';

  // 1. Recommended
  if (typeof window[fn] === 'function') {
    window[fn](args);
  }

  // 2. Recommended
  if (typeof myFnCollection[fn] === 'function') {
    myFnCollection[fn](args);
  }

  // 3. Eval is evil ;)
  if (typeof eval(fn) === 'function') {
    eval(fn)(args);
  }

我只是想发布一个稍微改变了的Jason Bunting非常有用的函数。

首先,我通过向slice()提供第二个参数简化了第一个语句。最初的版本在除IE之外的所有浏览器中都运行良好。

其次,我在return语句中用context替换了它;否则,在执行目标函数时,它总是指向window。

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

不要使用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);

在我的代码中有一个非常相似的东西。 我有一个服务器生成的字符串,其中包含一个函数名,我需要作为第三方库的回调传递。所以我有一个代码,接受字符串并返回一个指向函数的“指针”,如果没有找到,则为空。

我的解决方案非常类似于“Jason Bunting的非常有用的功能”*,尽管它不能自动执行,而且上下文总是在窗口上。但这是很容易修改的。

希望这能对别人有所帮助。

/**
 * 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;
}

这对我来说很管用:

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

我希望这有用。