当名称为字符串时,如何执行JavaScript函数

当名称为字符串时,如何执行JavaScript函数,javascript,Javascript,我将JavaScript中的函数名作为字符串。如何将其转换为函数指针,以便稍后调用 根据具体情况,我可能还需要将各种参数传递给该方法 有些函数可能采用名称空间.namespace.function(args[…])对另一个问题的回答向您展示了如何做到这一点: 基本上,你可以说 window["foo"](arg1, arg2); 或者正如许多其他人所建议的,您可以使用eval: eval(fname)(arg1, arg2); 尽管这是非常不安全的,除非你完全确定你在评估什么。两件事: 避

我将JavaScript中的函数名作为字符串。如何将其转换为函数指针,以便稍后调用

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


有些函数可能采用
名称空间.namespace.function(args[…])

对另一个问题的回答向您展示了如何做到这一点:

基本上,你可以说

window["foo"](arg1, arg2);
或者正如许多其他人所建议的,您可以使用eval:

eval(fname)(arg1, arg2);
尽管这是非常不安全的,除非你完全确定你在评估什么。

两件事:

  • 避免评估,这是非常危险和缓慢的

  • 其次,你的功能存在于何处并不重要,“全局性”是不相关的
    x.y.foo()
    可以通过
    x.y['foo']()
    x['y']['foo']()
    甚至
    window['x']['y']['foo']()启用。你可以像这样无限期地连锁


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

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

window["functionName"](arguments);
但是,这不适用于命名空间的函数:

window["My.Namespace.functionName"](arguments); // fail
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);
}
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);
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 );
}
这是您将如何做到的:

window["My"]["Namespace"]["functionName"](arguments); // succeeds
为了简化操作并提供一定的灵活性,这里提供了一个方便的功能:

window["My.Namespace.functionName"](arguments); // fail
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);
}
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);
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 );
}
注意,您可以在任何上下文中传递,因此这与上面的操作相同:

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

我只是想发布一个稍微修改过的版本

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

第二,我在return语句中将其替换为context;否则,在执行目标函数时,它总是指向窗口

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);
}
function executeFunctionByName(functionName,context/*,args*/){
var args=Array.prototype.slice.call(参数,2);
var namespace=functionName.split(“.”);
var func=namespaces.pop();
for(var i=0;i
您只需通过
窗口[]
将字符串转换为指针即可。 例如:


现在你可以像指针一样使用它。

还有一些非常有用的方法


关于Jason和Alex帖子的更多细节。我发现在上下文中添加默认值很有帮助。只需放置
context=context==未定义?窗口:上下文在函数的开头。您可以将
window
更改为您首选的上下文,这样您就不必每次在默认上下文中调用时都传入相同的变量。

如果您想使用
window[“functionName”]
调用对象的函数而不是全局函数。你可以这样做

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

var now=new Date();
now["getFullYear"]()

你能不能不这样做:

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

您还可以使用此方法执行任何其他JavaScript。

所有答案都假定可以通过全局范围(窗口)访问函数。然而,OP没有做出这一假设

如果函数位于局部作用域(也称为闭包)中,并且没有被其他局部对象引用,则会带来厄运:您必须使用
eval()
AFAIK,请参阅

为了补充Jason Bunting的答案,如果您使用的是nodejs或其他东西(这在dom js中也适用),您可以使用
这个
而不是
窗口
(请记住:eval是邪恶的

this['fun'+'ctionName']();

小心!!!

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

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


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

惊讶地发现没有提到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 functionWithoutArguments = function(){
    console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);
var functionWithArguments = function(arg1, arg2) {
    console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");
要运行深度命名空间函数,请执行以下操作:

window["My.Namespace.functionName"](arguments); // fail
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);
}
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);
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 );
}

我的代码中有一个非常相似的东西。 我有一个服务器生成的字符串,其中包含一个函数名,我需要将该函数名作为回调传递给第三方库。因此,我有一个代码获取该字符串并返回指向该函数的“指针”,如果找不到,则返回null

我的解决方案非常类似于“”,虽然它不会自动执行,并且上下文总是在窗口上。但是这很容易修改

希望这将有助于某人

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

因此,正如其他人所说,最好的选择无疑是:

window['myfunction'](arguments)
而且,如果函数的名称包含对象,则它将不起作用:

window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work
下面是我的函数版本,它将按名称执行所有函数(包括对象或不包括对象):

my={
代码:{
是:{
nice:函数(a,b){alert(a+,“+b);}
}
}
};
guy=函数(){alert('awesome');}
函数executeFunctionByName(str,args)
{
var arr=str.split('.');
var fn=窗口[arr[0]];
对于(变量i=1;iexecuteFunctionByName('guy');
我认为一种优雅的方法是在散列对象中定义函数。然后可以使用字符串从散列中引用这些函数

var customObject = {
  customFunction: function(param){...}
};
然后你可以打电话:

customObject['customFunction'](param);
其中customFunction是与对象中定义的函数匹配的字符串

更新

这个答案似乎对很多其他的程序员都有帮助,所以这里有一个更新版本

使用ES6,您还可以使用计算属性名,这将允许您避免使用魔术字符串

const FunctionNames=Object.freeze({
Fi
function testfunc(){
    return "hello world";
}

$( document ).ready(function() {

     $("div").html(eval("testfunc"));
});
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 );
}
// 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
  */
  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');
/* 
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.
this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();
global["funcname"]()