JavaScript中类似于PHP的call_user_func()函数的等效方法

6

有人知道这个吗?

我想使用变量名调用一个函数。


编辑:

我在这里发布了一个fiddle,展示了我正在尝试做的事情:

http://jsfiddle.net/sAzPA/

<div id="some">
  ...
</div>

js:

(function($){
  $.fn.MyPlugin = function(){

    return this.each(function(){
       var somefunction = function(arg1, arg2){ alert(arg1); },
           someotherfunction = function(arg1, arg2){ alert(arg2); },
           reallyimportantfunction = function(arg1, arg2){
            var foo = $(this).attr('id') + 'function';

            // here I want to call the function with the foo value as name, and pass it arg1 and arg2

            $()[foo](arg1, arg2); // <- doesn't work

           };

       reallyimportantfunction();
    });
  };  
})(jQuery);


jQuery(function($){
  $('#some').MyPlugin ();

});
3个回答

18
如果一个函数在全局级别定义,那么它自动成为window对象的子级。
因此,您可以在任何通常只调用functionName();的地方总是调用window.functionName();
此外,由于在JavaScript中对象的工作方式类似于关联数组,您可以使用数组语法调用任何对象的任何子元素,如:object['childName']。这包括函数,因此您可以对属于对象成员的任何函数执行object['functionName']();
将这两点结合起来,您可以这样调用任何全局定义的函数:
window['functionName']();

在上面的例子中,由于functionName是一个字符串,你可以在这些括号中使用变量,这意味着你拥有了与PHP的call_user_func()相同的功能。

[编辑]

正如我所述,这适用于任何对象。OP的评论表明,他想以这种方式使用的函数来自JQuery插件。它们很可能是JQuery对象的一部分,并且通常会像这样被调用:JQuery().functionName();(或者在JQuery位置使用$)。

Javascript语法允许我们在任何可以使用.functionName()的地方使用['functionName'](),因此,将上述JQuery示例更改为以下形式:

JQuery()['functionName']();`

但是这种技术可以适用于任何JavaScript对象。在使用 .functionName() 的任何地方,都可以将其替换为 ['functionName']()


这个函数(实际上是一组函数)是一个jQuery插件内的函数变量。我正在尝试使用来自同一插件的不同函数变量中的参数调用此函数。 - Alex
@Alex:在这种情况下,您想要的功能是 JQuery 对象的子级,因此根据我上面的答案,您应该能够执行 JQuery['functionName'](); - Spudley
@Alex:嗯。实际上,更可能是 JQuery()['functionName']()。但是如果你正常调用该函数,你通常会怎么称呼它?任何时候你可以使用 .functionName(),都可以将其替换为 ['functionName'](),因此请查看您当前使用该函数的情况,并根据需要调整这种技术。 - Spudley
在这种情况下,原始的 window['functionName']() 示例应该可以正常工作 -- 如下所示:window['somefunction']('bla', 'bla'); - Spudley
这似乎是在鼓励使用全局变量 :( - Warbo
显示剩余3条评论

2

有很多方法可以实现这个功能。最快且不安全的方法是执行以下步骤(注意:下面示例中的fnName是存储为字符串的函数名称):

eval(fnName)

然而,您也可以这样做。
            this[fnName]();//careful with "this" though. Try replacing with "window" if it doesnt work for you

或者通过传递参数来调用它。
this[fnName].apply(contextObject,argumentArray) //contextObject will be objest which will be referenced by the keyword "this" within the function body (fnName's body), argumentArrayy is the array of arguments you want to pass to function.

2
嗯,浏览器JavaScript本质上是不安全的。客户端可以随意更改代码。我更担心使用PHP的eval()。只需确保您严格检查提交的任何数据,服务器端即可。 - gnud
这是非常正确的。然而,eval函数经常被误解。大多数程序员一看到eval就会立刻喊出“邪恶!”然而,在某些情况下,eval确实非常有用并且值得推荐! - Nikhil
真实的案例确实存在,但它们非常罕见。 - Spudley
1
浏览器的用户不是敌人;试图对他们造成伤害的恶意用户才是。我们可以通过转义用户提供的数据来防止 XSS,但是 'eval' 可以使该数据再次变得有害!我们使用 'eval' 越多,恶意用户就越有机会找到一种方法将其数据传递给它,从而绕过我们的 XSS 预防措施。此外,“eval” 还可能妨碍代码分析,例如要求 IDE 查找所有函数的使用情况。 - Warbo

1
var a = function(foo) {console.log(foo);}

a.call(null, 'test');
a('test');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接