我有一个JavaScript函数名的字符串,如何将其转换为函数指针以便稍后调用?
根据情况,我可能需要将各种参数传递到方法中。
一些函数可能采用namespace.namespace.function(args[...])
的形式。
我有一个JavaScript函数名的字符串,如何将其转换为函数指针以便稍后调用?
根据情况,我可能需要将各种参数传递到方法中。
一些函数可能采用namespace.namespace.function(args[...])
的形式。
以下是我最终在一个项目中实现的一个更加健壮和可重用的解决方案。
一个FunctionExecutor构造函数
使用方法:
let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)
executor.execute("one");
executor.execute("three");
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和Alex的帖子,还有一个细节。我发现在上下文中添加默认值是很有帮助的。只需在函数开头添加context = context == undefined? window:context;
即可。您可以将window
更改为您喜欢的任何上下文,并且这样您每次在默认上下文中调用它时都不需要传递相同的变量。
除了Jason Bunting的回答外,如果您正在使用nodejs或其他类似技术(在dom js中也适用),您可以使用this
代替window
(请记住:eval是邪恶的):
this['fun'+'ctionName']();
这里也有一些非常有帮助的方法。
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
};
window.ClientSideValidations.forms.location_form
等同于
window.ClientSideValidations.forms['location_form']
eval
很危险和邪恶,因为它可以运行任意代码。然而,如果你使用白名单方式来使用eval
,并假设你提前知道可能需要运行的所有函数名称,则eval
不再是安全问题,因为输入不再是任意的。白名单是一个好的且常见的安全模式。以下是一个示例:
function runDynamicFn(fnName, ...args) {
// can also be fed from a tightly controlled config
const allowedFnNames = ['fn1', 'ns1.ns2.fn3', 'ns4.fn4'];
return allowedFnNames.includes(fnName) ? eval(fnName)(...args) : undefined;
}
// test function:
function fn1(a) {
console.log('fn1 called with', a)
}
runDynamicFn('alert("got you!")')
runDynamicFn('fn1', 'foo')
let allowedFns = new Map(); allowedFns.set('fn1', fn1); allowedFns.set('ns1.ns2.fn3', ns1.ns2.fn3); ...
。如果使用 eval
是安全的,那么问题可能可以在不使用 eval
的情况下解决 :-P - Gershom Maes我喜欢简洁的解决方案,所以想出了这种更符合ES6的方式:
const executeByName = (name, originContext, ...args) => {
const namespaces = name.split('.');
const func = namespaces.pop();
const funcContext = namespaces.reduce((context, namespace) => context[namespace], originContext);
return funcContext[func](...args);
};
你所需要做的就是使用一个上下文或定义一个新的上下文,让你的函数所在。
你不仅限于 window["f"]();
这里有一个我如何使用一些动态调用来处理 REST 服务的例子。
/*
Author: Hugo Reyes
@ www.teamsrunner.com
*/
(function ( W, D) { // enclose it as a 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.
如果你想从一个字符串生成整个函数,那就是另一个答案。
同时请注意,你不仅限于一个命名空间,如果你的命名空间存在于my.name.space.for.functions.etc.etc.etc
,那么你的命名空间的最后一个分支包含了这个函数my.name.space.for.functions.etc.etc["function"]();
希望对你有所帮助。 H.
看起来很基础:
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
还有另一种类型的函数是类,例如尼尔斯·彼得索恩