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

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

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


当前回答

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

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>元素。

其他回答

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

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(“家伙”);

小心! !

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

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

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

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

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

以下是我对Jason Bunting / Alex Nazarov的精彩回答的贡献,其中包括Crashalot要求的错误检查。

鉴于这个(做作的)序言:

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

然后执行如下函数:

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

将允许您通过存储在字符串中的名称(命名空间或全局)调用javascript函数,带或不带参数(包括数组对象),为遇到的任何错误提供反馈(希望能够捕获它们)。

示例输出显示了它是如何工作的:

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

谢谢你非常有用的回答。我在我的项目中使用了Jason Bunting的功能。

我扩展了它,使用一个可选的超时,因为设置超时的正常方式不会工作。请看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 );