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

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

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


当前回答

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

我的解决方案非常类似于“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;
}

其他回答

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

一个更面向对象的解决方案…

下面是我最终为我的一个项目实现的一个健壮且可重用的解决方案。

一个FunctionExecutor构造函数

用法:

let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)

executor.execute("one");
executor.execute("three");

显然,在项目中,所有需要按名称调用的函数的添加都是通过循环完成的。

函数Executor:

function FunctionExecutor() {
  this.functions = {};

  this.addFunction = function (fn) {
    let fnName = fn.name;
    this.functions[fnName] = fn;
  }

  this.execute = function execute(fnName, ...args) {
    if (fnName in this.functions && typeof this.functions[fnName] === "function") {
      return this.functions[fnName](...args);
    }
    else {
      console.log("could not find " + fnName + " function");
    }
  }

  this.logFunctions = function () {
    console.log(this.functions);
  }
}

使用示例:

function two() {
  console.log("two"); 
}

function three() {
  console.log("three");
}

let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)

executor.execute("one");
executor.execute("three");

最简单的方法是像has元素一样访问它

window.ClientSideValidations.forms.location_form

window.ClientSideValidations.forms['location_form']

我忍不住要提到另一个技巧,如果你有一个未知数量的参数,这些参数也作为包含函数名的字符串的一部分被传递,那么这个技巧是有用的。例如:

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

如果你的Javascript运行在HTML页面上,你所需要的只是一个看不见的链接;您可以向onclick属性传递一个字符串,然后调用click方法。

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

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

或者在运行时创建<a>元素。

我只是想发布一个稍微改变了的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);
}