我有一个JavaScript函数的名称作为字符串。如何将其转换为函数指针以便稍后调用?
根据具体情况,我可能还需要将各种参数传递到方法中。
一些函数可以采用namespace.namespace.function(args[…])的形式。
我有一个JavaScript函数的名称作为字符串。如何将其转换为函数指针以便稍后调用?
根据具体情况,我可能还需要将各种参数传递到方法中。
一些函数可以采用namespace.namespace.function(args[…])的形式。
当前回答
你只需要通过window[<方法名>]将字符串转换为指针。 例子:
var function_name = "string";
function_name = window[function_name];
现在你可以把它当做一个指针。
其他回答
下面是我最终为我的一个项目实现的一个健壮且可重用的解决方案。
一个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");
我只是想发布一个稍微改变了的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);
}
这对我来说很管用:
var command = "Add";
var tempFunction = new Function("Arg1","Arg2", "window." + command + "(Arg1,Arg2)");
tempFunction(x,y);
我希望这有用。
不要使用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 / 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
*/