当我把它的名字作为一个string的时候如何执行一个JavaScript函数

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

根据具体情况,我可能也需要将各种理由传递给方法。

一些函数可能采用namespace.namespace.function(args[...])

除非你绝对肯定没有别的select否则不要使用eval。

如上所述,使用这样的东西将是最好的办法:

 window["functionName"](arguments); 

但是,这不适用于命名空间的function:

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

这是你将如何做到这一点:

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

为了使这更容易和提供一些灵活性,这里是一个方便的function:

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

只是觉得我会张贴一个稍微改变的版本的杰森·邦廷的非常有用的function 。

首先,我通过向slice()提供第二个参数来简化第一条语句。 原始版本在IE浏览器以外的所有浏览器上工作正常。

其次,我在回归声明中用上下文replace了这个 ; 否则,当目标函数被执行时, 总是指向窗口

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

这个问题的答案告诉你如何做到这一点: Javascript的Python的本地人()相当于?

基本上,你可以说

 window["foo"](arg1, arg2); 

或者像其他人所build议的那样,您可以使用eval:

 eval(fname)(arg1, arg2); 

虽然这是非常不安全的,除非你完全确定你在评估什么。

你能不能这样做:

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

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

我认为这样做的一个很好的方法是通过在一个散列对象中定义你的函数。 然后,您可以使用string从哈希引用这些函数。 例如

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

那么你可以打电话给:

 customObject['customFunction'](param); 

customFunction将是一个匹配在你的对象中定义的函数的string。

两件事情:

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

  • 其次,你的function在哪里并不重要,“全球性”是无关紧要的。 xyfoo()可以通过xy['foo']()x['y']['foo']()甚至window['x']['y']['foo']()来启用。 你可以像这样无限期地连锁。

您只需要通过window[<method name>]将string转换为指针。 例:

 var function_name = "string"; function_name = window[function_name]; 

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

所有的答案都假定函数可以通过全局范围(又名窗口)来访问。 但是,OP没有做出这个假设。

如果函数存在于本地作用域(aka closure)中,并且没有被其他本地对象引用,那么运气不好:你必须使用eval() AFAIK,参见dynamic调用javascript的本地函数

使用ES6,您可以按名称访问类方法:

 class X { method1(){ console.log("1"); } method2(){ this['method1'](); console.log("2"); } } let x = new X(); x['method2'](); 

输出将是:

 1 2 

小心!!!

一个应该尽量避免JavaScript中的string调用函数有两个原因:

原因1:某些代码混淆器会破坏您的代码,因为它们将更改函数名称,导致string无效。

原因2:维​​护使用这种方法的代码要困难得多,因为findstring调用的方法的用法要困难得多。

如果你想用window["functionName"]调用一个对象的函数而不是全局函数。 你可以这样做;

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

例:

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

这里是我对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 ); } 

将允许您通过名称存储在一个string名称空间或全局,有或没有参数(包括数组对象)调用一个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 */ 

惊讶地看到没有提到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); 

杰森和亚历克斯的post更多的细节。 我发现向上下文添加默认值很有帮助。 只要把context = context == undefined? window:context; context = context == undefined? window:context; 在函数的开始。 您可以将window更改为任何您喜欢的上下文,然后每次在默认上下文中调用此window时都不需要传入相同的variables。

在我的代码中有一个非常类似的东西。 我有一个服务器生成的string,其中包含一个函数名称,我需要作为第三方库的callback传递。 所以我有一个代码,该string并返回一个“指针”的函数,如果没有find它为空。

我的解决scheme非常类似于“ Jason Bunting非常有用的function ” * ,虽然它不会自动执行,并且上下文总是在窗口中。 但是这可以很容易地修改。

希望这会对某人有所帮助。

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

还有一些非常有用的方法。

http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx

 var arrayMaker = { someProperty: 'some value here', make: function (arg1, arg2) { return [ this, arg1, arg2 ]; }, execute: function_name }; 

所以,像其他人一样,绝对是最好的select是:

 window['myfunction'](arguments) 

就像Jason Bunting所说 ,如果你的函数的名字包含一个对象,它将不起作用:

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

所以这里是我的版本的函数,将执行所有function的名称(包括对象或不):

 my = { code : { is : { nice : function(a, b){ alert(a + "," + b); } } } }; guy = function(){ alert('awesome'); } function executeFunctionByName(str, args) { var arr = str.split('.'); var fn = window[ arr[0] ]; for (var i = 1; i < arr.length; i++) { fn = fn[ arr[i] ]; } fn.apply(window, args); } executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']); executeFunctionByName('guy'); 

我无法抗拒的提到另一个技巧,这有助于如果你有一个未知数量的参数也作为包含函数名称的string的一部分被传递 。 例如:

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

如果您的Javascript运行在HTML页面上,您只需要一个隐形链接; 你可以将一个string传递给onclick属性,并调用click方法。

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

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

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

最简单的方法就是像拥有元素一样访问它

 window.ClientSideValidations.forms.location_form 

和…一样

 window.ClientSideValidations.forms['location_form'] 

你可以在eval("functionname as string")调用javascript函数。 像下面这样:(eval是纯javascriptfunction)

 function testfunc(){ return "hello world"; } $( document ).ready(function() { $("div").html(eval("testfunc")); }); 

工作示例: https : //jsfiddle.net/suatatan/24ms0fna/4/

若要添加到Jason Bunting的答案,如果您使用的是nodejs或其他东西(这也适用于dom js),您可以使用this代替window (并记住:eval是邪恶的

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

不使用eval('function()')你可以使用new Function(strName)创build一个新的函数。 下面的代码使用FF,Chrome,IE进行testing。

 <html> <body> <button onclick="test()">Try it</button> </body> </html> <script type="text/javascript"> function test() { try { var fnName = "myFunction()"; var fn = new Function(fnName); fn(); } catch (err) { console.log("error:"+err.message); } } function myFunction() { console.log('Executing myFunction()'); } </script> 
 use this function executeFunctionByName(functionName, context /*, args */) { var args = [].slice.call(arguments).splice(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 namefunction = 'jspure'; // String function jspure(msg1 = '', msg2 = '') { console.log(msg1+(msg2!=''?'/'+msg2:'')); } // multiple argument // Results ur test window[namefunction]('hello','hello again'); // something... eval[namefunction] = 'hello'; // use string or something, but its eval just one argument and not exist multiple 

存在其他types的function是 ,看看例子nils petersohn

感谢非常有帮助的答案。 我在我的项目中使用了Jason Bunting的function 。

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

有几个executeByName函数在这里工作正常,除非名称包含方括号 – 我遇到的问题 – 因为我有dynamic生成的名称。 所以上面的函数会失败的名字

app.widget['872LfCHc']['toggleFolders']

作为一种补救措施,我已经将function考虑在内,也许有人会发现它有用:

从CoffeeScript生成:

 var executeByName = function(name, context) { var args, func, i, j, k, len, len1, n, normalizedName, ns; if (context == null) { context = window; } args = Array.prototype.slice.call(arguments, 2); normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.'); ns = normalizedName.split("."); func = context; for (i = j = 0, len = ns.length; j < len; i = ++j) { n = ns[i]; func = func[n]; } ns.pop(); for (i = k = 0, len1 = ns.length; k < len1; i = ++k) { n = ns[i]; context = context[n]; } if (typeof func !== 'function') { throw new TypeError('Cannot execute function ' + name); } return func.apply(context, args); } 

为了更好的可读性检查CoffeeScript版本:

 executeByName = (name, context = window) -> args = Array.prototype.slice.call(arguments, 2) normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.') ns = normalizedName.split "." func = context for n, i in ns func = func[n] ns.pop() for n, i in ns context = context[n]; if typeof func != 'function' throw new TypeError 'Cannot execute function ' + name func.apply(context, args) 
  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'); 

更多的OOP解决scheme…

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

这里是我如何使用某些REST服务的一些dynamic调用的例子。

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

如果你想从一个string生成整个函数,这是一个不同的答案。 还请注意,您不限于单个名称空间,如果您的名称空间存在为my.name.space.for.functions.etc.etc.etc ,则您的名称空间的最后一个分支包含函数my.name.space.for.functions.etc.etc["function"]();

希望它有帮助。 H。

这对我有用:

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

我希望这个工程。