Javascript JQuery:动态调用函数

Javascript JQuery:动态调用函数,javascript,jquery,Javascript,Jquery,我已将onClick事件句柄附加到标记。单击时,我想选择一个属性——比方说,fn;我想调用前面提到的函数作为属性值 以下代码不起作用 <html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script> <script language="JavaScript"> va

我已将onClick事件句柄附加到标记。单击时,我想选择一个属性——比方说,fn;我想调用前面提到的函数作为属性值

以下代码不起作用

<html>
<head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
    <script language="JavaScript">
        var Test = Test? Test : new Object();
        $(document).ready(function(){
            Test.main();
        })
        Test.sub = function(){
            alert('called');
        }
        Test.main = function(){
            $('.caller').click(function(e){
                e.preventDefault();
                var fn = $(this).attr('fn');
                alert('calling: '+fn);
                return fn();
            });
        }
    </script>
</head>
<body>
    <a class="caller" fn="Test.sub" href="#">test call</a>
</body>
</html>

var测试=测试?测试:新对象();
$(文档).ready(函数(){
Test.main();
})
Test.sub=函数(){
警报(“被呼叫”);
}
Test.main=函数(){
$('.caller')。单击(函数(e){
e、 预防默认值();
var fn=$(this.attr('fn');
警报(“呼叫:”+fn);
返回fn();
});
}
我的问题是

  • 可能吗
  • 我做错了什么
  • 解决这个问题的正确方法是什么
谢谢
尼桑

可能吗

对。如果您将链接更改为仅包含
sub

<a class="caller" fn="sub" href="#">test call</a>
您检索的值是一个字符串。如果喜欢使用括号表示法(
[]
),可以使用字符串索引对象的属性,因此所有这些都是等效的:

Test.sub();
Test['sub']();
var fn = 'sub';
Test[fn]();
我做错了什么

你就快到了。字符串中有“Test.sub”,但由于它是字符串,而不是函数,所以无法调用它。就像这样做:

"Test.sub"();
…这显然不是你想要的。:-)

解决这个问题的正确方法是什么

在技术方面,上述解决了问题。我有一部分担心在属性中有实际的函数名,想说“取而代之的是查找表”,但您的
Test
对象基本上就是查找表,所以

旁注:在这种情况下,您可能会看到人们使用
eval
。通常这是因为他们没有意识到可以用括号表示法索引到对象中<最好避免代码>评估


离题1:您的属性
fn
无效(无效=不会)。在HTML4和更早的版本中,所有自定义属性都是无效的,尽管我见过的每个桌面浏览器都允许它们(浏览器让我们可以处理很多事情)。从HTML5开始,对该功能的需求已经被听到,我们可以拥有有效的自定义属性,但它们必须以
数据-
开始,以便验证器知道它们是自定义的。因此,如果验证是您工作流程的一部分(这通常是一个好主意),您可以使用
data fn=“sub”
,而不是简单地使用
fn=“sub”


非主题#2:如果要保存一些键入内容,请使用
{}
而不是
新对象()
。例如:

var Test = Test? Test : {};
如果您想节省更多,请使用:

试试这个:

<a class="caller" fn="Test.sub()" href="#">test call</a>

关于“主题外”部分的注意:虽然HTML4不允许自定义属性,但我相信每个(哦!)主要的[桌面]浏览器(历史和当前)都已经默默地将它们接受到可访问的DOM中,至少从允许JS访问DOM开始。@pst:确实如此。我通常会提到这一点,但上面似乎没有提到。在调用该方法之前,我仍然会使用
eval
或一些更复杂的逻辑来解除自己对该属性的依赖,该属性真正命名了
Test
类的属性。在现实生活中,它可能会出现命名,例如,一个用户定义的
窗口
函数,在其名称之前有或没有
窗口。
,然后您的方法将不起作用。使用
eval
,您不必关心调用的是哪个对象的函数。So
eval(fn+“()”)是我的选择。只需将其包装在
中,然后尝试。。。可能是catch
。@Michael:
eval
编译并执行任意代码,它可以做任何事情。我就是不愿意做。通过将属性解析为其组件片段(例如,“Test.sub”可以拆分为
['Test',sub']
并有意处理),而无需依赖
eval
的jackhammer,就可以轻松处理上面列出的问题。事实上,这些问题中的大多数根本不是问题,而是特性——包含了使用属性中的代码/命令/任何东西可以做什么的范围。@t.J.Crowder——您的代码对我帮助很大。谢谢你的解释。
var Test = Test || {};
<a class="caller" fn="Test.sub()" href="#">test call</a>
$('.caller').click(function(e){
    e.preventDefault();
    var fn = eval($(this).attr('fn'));
    fn;
});