How to execute a JavaScript function when I have its name as a string
我将javascript中的函数名作为字符串。如何将其转换为函数指针以便稍后调用?
根据具体情况,我可能还需要将各种参数传递到方法中。
有些功能可以采用
不要使用
如前所述,使用这样的方法是最好的方法:
1 | window["functionName"](arguments); |
但是,这不适用于命名空间的d函数:
1 | window["My.Namespace.functionName"](arguments); // fail |
您可以这样做:
1 | window["My"]["Namespace"]["functionName"](arguments); // succeeds |
为了使这更容易并提供一些灵活性,这里有一个方便的功能:
1 2 3 4 5 6 7 8 9 | 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); } |
你可以这样称呼它:
1 | executeFunctionByName("My.Namespace.functionName", window, arguments); |
注意,您可以在任何上下文中传递,因此这与上面的操作相同:
1 | executeFunctionByName("Namespace.functionName", My, arguments); |
- 你知道你不需要整个"func"结构吗?context.apply"单独使用很好
- 当然,我知道这一点——但是我编写函数的方式为那些阅读它的人提供了一些清晰的信息,这些信息可能无法完全了解正在发生的事情。我写了这个函数,认识到阅读它的人可能需要一些帮助。不过,我会提供一个替代方案,因为你问…
- 记住这一点——代码足够清晰,那些知道的人知道。如果你和我一样,并且知道你在做什么,那么如果你使用了这个代码,你就可以自己做这些更改。堆栈溢出是为了教育别人,我认为我的代码对于新手来说更容易理解。谢谢!
- 是否存在窗口["funcname"]返回未定义的情况?这就是我现在面临的问题。调用代码和函数在两个单独的JS文件中定义。我试着把它们添加到同一个文件中,但没有什么不同。
executeFunctionByName 只有当你把它放到全球范围内时才有效。如果你不这样做,你会得到Uncaught TypeError: Illegal invocation 。我想最后一行应该是return context[func].apply(this, args); 。- 我想这里有问题。当您调用
My.Namespace.functionName() 时,this 将引用My.Namespace 对象。但是当你打电话给executeFunctionByName("My.Namespace.functionName", window) 时,没有办法让this 提到同样的事情。也许它应该使用最后一个名称空间作为作用域,或者如果没有名称空间,则使用window 。或者您可以允许用户将作用域指定为参数。 - 杰出的。唯一的问题-是否有一种方法可以使函数在executeFunctionByName()中存在(即可调用)?
- 我不能给一个函数传递多个参数,比如
executeFunctionByName("testFunction", window, new Array("false","
Data loaded!</td></tr>"));不起作用,有人能帮我找出我做错了什么吗?-结果是数组中的两个元素都被传递到函数testfunction的第一个参数中。 - 是否可以传入"new"关键字以按名称实例化对象?
Uncaught TypeError: Object [object global] has no method 'x' - 我试图使用这个版本,但它总是抛出非法调用。@alexanazarov变体(上下文作为应用的参数)的工作方式很有魅力。
- 那么变量
arguments 是全局变量吗?- 我不能让它工作(我一直不能阅读未罚款的
。有人能让它工作吗? - 不适用于IE8及以下版本。如果需要对旧IE浏览器的支持,请使用AlexNazarov的答案。
- 这个解决方案根本不起作用。还是我错过了什么?
- @brentonstrine在不使用onload:jsfiddle.net/pgplmdwn包装JavaScript代码的情况下重试。
- 在javascript 1.8中,您只需执行
functionName.split('.').reduce(function(obj, key){ return obj[key]; }, window); - 如果要缩小JS,请注意。如果希望在小型化生产代码中使用函数名=>函数,则可能需要创建函数名映射。
- 不幸的是,这个答案有缺陷,因为它没有正确设置执行上下文。遗憾的是,这些年来这里一直没有解决这个问题。请使用下面的@alexanazarov的答案,他会理解的。
- 我必须取消对
args 参数的注释,然后在第一行重写它的值,这样typescript就不会因为调用与函数签名不匹配而惊慌失措。- 有道理,@alan-typescript有点严格(这就是为什么我不喜欢使用它)。;)
- 这个函数中有很多可以用一行代码完成的功能。@巴克斯,我是来给你那行代码的,你已经把它放在这里了。干杯。对于那些正在寻找解决方案的人来说,如果字符串或函数为空,我将使用一个简单的函数作为新的答案。
我只是想发布一个稍微修改过的版本,杰森·邦廷的非常有用的功能。
首先,我通过向slice()提供第二个参数简化了第一条语句。原始版本在除IE以外的所有浏览器中都工作正常。
其次,我在RETURN语句中将其替换为上下文;否则,在执行目标函数时,它总是指向窗口。
1
2
3
4
5
6
7
8
9function 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);
}- 不检查"functionname"是否实际存在?
- 我提供了一个包含错误检查的答案。
- 我认为麦克的回答被低估了。我不是一个专家,但它似乎是经过深思熟虑和强大的。
另一个问题的答案向您展示了如何做到这一点:JavaScript相当于python的locals()?
基本上,你可以说
1window["foo"](arg1, arg2);或者像其他许多人建议的那样,您可以使用eval:
1eval(fname)(arg1, arg2);虽然这是非常不安全的,除非你完全确定你在逃避什么。
- 第一种形式更可取
- 只有当所有其他方法都失败时,才使用eval作为最后手段。
- 它是……但是它是否可以与这样的函数一起工作:x.y.z(args)?
- 是的,是的。请看下面我的答案
你不能这样做吗:
1
2
3var codeToExecute ="My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();您还可以使用此方法执行任何其他JavaScript。
- 这对我很有用。谢谢。
- 与函数一起传递偶数参数时工作
- 函数返回呢?
- 这与
eval("My.Namespace.functionName()"); 有什么不同? - @彼得涅夫把第一行改成
var codeToExecute ="return My.Namespace.functionName()"; 。 - 这对我很有用,因为我可以支持圆括号内的论点。只是需要注意的是,与前面的答案不同,这种方法需要在方法名后面加上圆括号。
- @developerbmw,这里是answer stackoverflow.com/questions/4599857/&hellip;
- 也为我工作!谢谢@ Coley
- 谢谢。在firefox和window中都可以使用["functionStringName"]在FF中似乎不起作用。
我认为这样做的一种优雅方式是在散列对象中定义函数。然后可以使用字符串从散列中引用这些函数。例如
1
2
3var customObject = {
customFunction: function(param){...}
};然后你可以打电话给:
1customObject['customFunction'](param);其中,customFunction将是与对象中定义的函数匹配的字符串。
- @伊布森夫,谢谢你的评论,以帮助我确定这是最好的回应。我创建了一个函数对象数组,然后用它创建了一个deferred.promises数组。我在下面放了一些示例代码。(我不想创建一个新的回复并借用鲁本的回复。)
- 函数getmydata(arrayofobjectswithids)var functionarray=arrayofobjectswithids.map(函数(值)return mygetdatafunction:myservice.getmydata(value.id)var promises=functionarray.map(函数(getdatafunction)var deferred=q.defer();getdatafunction.mygetdatafunction.success(函数(数据)延迟。解决(数据))。错误(function(error)deferred.reject(););返回deferred.promise;);$q.all(promises).then(function(dataarray)//do task);
- 这很好,我只添加了下划线/lodash来验证它是否是一个函数。然后运行
使用ES6,可以按名称访问类方法:
1
2
3
4
5
6
7
8
9
10
11class X {
method1(){
console.log("1");
}
method2(){
this['method1']();
console.log("2");
}
}
let x = new X();
x['method2']();输出将是:
1
21
2- 最好的纯javascript…上帝…删除不起作用的类,但它是可以的。谢谢!
- 这是我很久以来一直在寻找的东西。谢谢!
- 大家!在这里!ES6 FTW!!!!!
- ES2015与此无关。您可以使用纯对象或通过
Object.create() 进行原型委托来实现相同的目标。const myobj=method1()console.log('1'),method2()console.log('2')myobj['method1']();//1 myobj['method2']();//2
两件事:
避免逃避,这是非常危险和缓慢的。
其次,你的职能在哪里并不重要,"全局性"是不相关的。
x.y.foo() 可以通过x.y['foo']() 或x['y']['foo']() 甚至window['x']['y']['foo']() 启用。你可以像这样无限期地连锁。
- 但是你不能用window['x.y.z']()来调用x.y.z()。
- 不,尼克,你不能那样做。我的答案提供了一个通用的解决方案…
所有的答案都假设可以通过全局范围(aka窗口)访问函数。然而,OP并没有做出这样的假设。
如果函数位于本地作用域(亦称闭包)中,并且没有被其他本地对象引用,那么不幸的是:您必须使用eval()afaik,请参见在javascript中动态调用本地函数
- 哥们儿,谢谢你指出了这一点!我以为我疯了一秒钟。
您只需要通过
window[ 将字符串转换为指针即可。例子:] 1
2var function_name ="string";
function_name = window[function_name];现在你可以像指针一样使用它。
- 这似乎是一种更安全的方法。
- 很清楚,很有效!
以下是我对杰森·邦廷/亚历克斯·纳扎罗夫的优秀答案的贡献,其中包括了Crashalot要求的错误检查。
鉴于此(人为的)序言:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16a = 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(){};然后执行以下功能:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32function 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函数,无论是名称空间的还是全局的,无论是否有参数(包括数组对象),对遇到的任何错误提供反馈(希望能够捕捉到它们)。
示例输出显示了它的工作方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76// 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
*/- 不知道……这是一个很好的努力,很明显。但我觉得"太宽泛了"…
- 呵呵?问答/教学平台也是如此。我很乐意提供我能想到的所有例子,希望能给大家带来启发。对我来说,这就是重点。
- 如果你还是要评估函数名,为什么不直接使用它呢?
- 这对我不起作用。我有一个命名函数a.b.c.d,其中d是函数名。调用executeFunctionByName("a.b.c.d",window)在检查
if( typeof context[ functionName ] !== 'function' ) 的行上失败,因为上下文-window-是定义的,是一个对象和一个数组,但window〔a.b.c.d〕不存在,因为它在接受的回答中被标识为一个问题:window["My.Namespace.functionName"](arguments); // fail 。
如果要使用
window["functionName"] 调用对象的函数,而不是全局函数。你可以像这样做;1
2var myObject=new Object();
myObject["functionName"](arguments);例子:
1
2var now=new Date();
now["getFullYear"]()小心!!!!
应该尽量避免在javascript中按字符串调用函数,原因有两个:
原因1:一些代码模糊器会破坏代码,因为它们会更改函数名,使字符串无效。
原因2:维护使用此方法的代码要困难得多,因为查找字符串调用的方法的用法要困难得多。
根据您所在的位置,您还可以使用:
1
2
3
4
5this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();或者,在诺迪斯
1global["funcname"]()很惊讶没有提到设置时间。
运行不带参数的函数:
1
2
3
4var functionWithoutArguments = function(){
console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);要用参数运行函数:
1
2
3
4var functionWithArguments = function(arg1, arg2) {
console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");要运行深度命名函数:
1
2
3
4
5
6
7
8
9
10var _very = {
_deeply: {
_defined: {
_function: function(num1, num2) {
console.log("Execution _very _deeply _defined _function :", num1, num2);
}
}
}
}
setTimeout("_very._deeply._defined._function(40,50)", 0);- 这并不能回答这个问题。要评论或要求作者澄清,请在他们的帖子下面留下评论-你可以随时对自己的帖子发表评论,一旦你有足够的声誉,你就可以对任何帖子发表评论。
- 请添加一个示例,说明如何使用几个参数来调用
runMe 。 - 你可以像其他函数一样调用它。只是它将是一个字符串。
var functionName ="addNumbers(10, 20)"; setTimeout(functionName,10); - @阿披实基诺下次最好给出一个完整的答案,而不仅仅是一小段。这个问题涉及到
run.run.runMe ,而不仅仅是runMe 和论点。请接受这是一个友好的反馈。 - @Astrocb确实提供了这个问题的初步答案。因此,在这里给出更正反馈比投票赞成结束更合适。
- @Lexicore我投票赞成在审查队列中删除,因为它不能清楚地提供问题的实质性答案,而且它本身也没有什么价值。
- @Lexicore感谢您的反馈。这是我的错。我认为答案太微不足道,无法提供示例。编辑了答案。
- 此方法可能存在巨大的缺陷,因为它将执行置于呈现队列的末尾,从而使此调用具有异步性。
- 我喜欢这个答案,它似乎符合我的要求。
下面是我的ES6方法,它允许您以字符串或函数名的形式调用函数,还允许您向不同类型的函数传递不同数量的参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function fnCall(fn, ...args)
{
let func = (typeof fn =="string")?window[fn]:fn;
if (typeof func =="function") func(...args)
else console.error(`${fn} is Not a function!`);
}
function example1(arg1){console.log(arg1)}
function example2(arg1, arg2){console.log(arg1 +" and " + arg2)}
function example3(){console.log("No arguments!")}
fnCall("example1","test_1");
fnCall("example2","test_2","test3");
fnCall(example3);
fnCall("example4"); // should raise an error in console所以,正如其他人所说,最好的选择是:
1window['myfunction'](arguments)正如JasonBunting所说,如果函数名包含一个对象,那么它将不起作用:
1
2window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work下面是我的函数版本,它将按名称执行所有函数(包括对象与否):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22my = {
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');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24let 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解决方案…
关于杰森和亚历克斯的帖子的更多细节。我发现向上下文添加默认值很有帮助。只需将
context = context == undefined? window:context; 放在函数的开头。您可以将window 更改为您首选的上下文,然后在默认上下文中每次调用它时,您就不需要传入相同的变量。我的代码中有一个非常相似的东西。我有一个服务器生成的字符串,其中包含一个函数名,我需要将其作为第三方库的回调传递。所以我有一个代码,它接受字符串并返回一个指向函数的"指针",如果找不到,则返回空值。
我的解决方案非常类似于"JasonBunting的非常有用的函数"*,虽然它不自动执行,并且上下文总是在窗口上。但这很容易修改。
希望这对某人有帮助。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25/**
* 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;
}最简单的方法是像has元素一样访问它
1window.ClientSideValidations.forms.location_form一样
1window.ClientSideValidations.forms['location_form']为了补充Jason Bunting的答案,如果你使用nodejs或其他东西(这在dom js中也适用),你可以使用
this 而不是window (记住:eval是邪恶的:1this['fun'+'ctionName']();我忍不住要提到另一个技巧,如果有未知数量的参数也作为包含函数名的字符串的一部分传递,这将有所帮助。例如:
var annoyingstring = 'call_my_func(123, true,"blah")'; 如果您的javascript运行在一个HTML页面上,那么您所需要的只是一个不可见的链接;您可以将一个字符串传递到
onclick 属性,并调用click 方法。1
2$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();或者在运行时创建
元素。 - 创造性的解决方案,但这对对象或数组类型参数不起作用。
- 这是在引擎盖下面用eval…真的要绕着树丛跑来跑去
还有一些非常有用的方法。
http://devlicio.us/blogs/sergio eu pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
1
2
3
4
5
6
7var arrayMaker = {
someProperty: 'some value here',
make: function (arg1, arg2) {
return [ this, arg1, arg2 ];
},
execute: function_name
};由于
eval() 是邪恶的,而new Function() 不是实现这一点的最有效方法,因此这里有一个快速的js函数,它从字符串中的名称返回函数。- 适用于命名空间的函数
- 如果字符串为空/未定义,则回滚到空函数
- 如果找不到函数,则回退到空函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function convertStringtoFunction(functionName){
var nullFunc = function(){}; // Fallback Null-Function
var ret = window; // Top level namespace
// If null/undefined string, then return a Null-Function
if(functionName==null) return nullFunc;
// Convert string to function name
functionName.split('.').forEach(function(key){ ret = ret[key]; });
// If function name is not available, then return a Null-Function else the actual function
return (ret==null ? nullFunc : ret);
}用途:
1convertStringtoFunction("level1.midLevel.myFunction")(arg1, arg2, ...);您所要做的就是使用一个上下文或定义一个您的函数所在的新上下文。您不限于
window["f"](); 。下面是一个示例,说明如何对某些REST服务使用动态调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39/*
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.如果您想从一个字符串生成整个函数,这是另一个答案。另外,请注意,您不限于单个名称空间,如果您的名称空间以
my.name.space.for.functions.etc.etc.etc 的形式存在,则您名称空间的最后一个分支包含my.name.space.for.functions.etc.etc["function"](); 的功能。希望它有帮助。H.
您也可以在
eval("functionname as string") 中调用javascript函数。如下:(eval是纯javascript函数)1
2
3
4
5
6
7
8function testfunc(){
return"hello world";
}
$( document ).ready(function() {
$("div").html(eval("testfunc"));
});工作示例:https://jsfiddle.net/suatatan/24ms0fna/4/
- 这个很好用,很简单
- 而且速度也很慢。
谢谢你的帮助。我正在我的项目中使用Jason Bunting的函数。
我将它扩展为与可选超时一起使用,因为设置超时的正常方法不起作用。见阿披实基诺的问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26function 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 );基本情况:
1
2
3
4
5
6
7
8
9var 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存在其他类型的函数是类和示例nils petersohn
这对我很有用:
1
2
3var command ="Add";
var tempFunction = new Function("Arg1","Arg2","window." + command +"(Arg1,Arg2)");
tempFunction(x,y);我希望这能奏效。
1
2
3
4
5
6
7
8
9
10
11use 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);
}- 为什么?没有解释的答案很可能是无用的。
不使用
eval('function()') ,您可以使用new Function(strName) 创建一个新函数。下面的代码是用FF,Chrome,IE测试的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<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()');
}这里有几个
executeByName 函数可以很好地工作,除非名称包含方括号(我遇到的问题),因为我动态生成了名称。所以上面的函数会在如下名称上失败app.widget['872LfCHc']['toggleFolders'] 作为补救措施,我也考虑到了这一点,也许有人会发现它是有用的:
从coffeescript生成:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23var 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);
}要获得更好的可读性,请检查coffeeesccript版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14executeByName = (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)
Copyright © 码农家园 联系:[email protected]