OOP javascript - 无法在页面加载时分配onclick事件处理程序

时间:2011-01-11 11:16:48

标签: javascript javascript-events

所以我正在尝试使用javascript进行自定义标签系统。但是,为了重用我想用OOP风格编写的代码。这就是我到目前为止:

function Tabs()
{

    this.tabArray = new Array(arguments.length);
    this.tabArrayC = new Array(arguments.length);

    for(i=0;i<arguments.length;i++)
    {
        this.tabArray[i] = arguments[i];
        this.tabArrayC[i] = arguments[i]+'_content';
    }

    this.setClickable = setClickable;

    function setClickable()
    {   

        for(i=0;i<this.tabArray.length;i++)
        {

                document.getElementById(this.tabArray[i]).onclick = function()
                {

                    alert(this.tabArray[i]);

                }

        }

    }

}

function init()
{
    tab = new Tabs('tab1','tab2','tab3','tab4');
    tab.setClickable();
}

window.onload = init();

现在就是这笔交易。我想将onclick事件处理程序分配给在Tabs'类'构造函数中传递的每个选项卡。所以稍后在代码中写下类似的东西:

<div id="tab1">Tab1</div>
<div id="tab2">Tab2</div>
<div id="tab3">Tab3</div>
<div id="tab4">Tab4</div>

之前设置的代码:

document.getElementById(this.tabArray[i]).onclick = function()
{

                    alert(this.tabArray[i]);

}

......将被执行。我希望我解释得那么好。有任何想法吗?

2 个答案:

答案 0 :(得分:6)

您的setClickable功能存在三个问题(修改:以及您如何调用init的问题):

  1. this在您生成的事件处理程序中具有与预期不同的含义。 (更多信息:You must remember this

  2. 一个闭包(关闭数据的函数,如i变量)有一个持久对变量的引用,而不是它的价值。因此,所有处理程序将在运行时看到i,而不是在它们创建时。 (更多信息:Closures are not complicated

  3. 您没有声明i,因此您正在成为the Horror of Implicit Globals的牺牲品。

  4. 以下是解决这些问题的一种方法:

    function setClickable()
    {   
        var i;           // <== Declare `i`
        var self = this; // <== Create a local variable for the `this` value
    
        for(i=0;i<this.tabArray.length;i++)
        {
                                                             // v=== Use a function to construct the handler
            document.getElementById(this.tabArray[i]).onclick = createHandler(i);
        }
    
        function createHandler(index)
        {
            // This uses `self` from the outer function, which is the
            // value `this` had, and `index` from the call to this
            // function. The handler we're returning will always use
            // the `index` that was passed into `createHandler` on the
            // call that created the handler, so it's not going to change.
            return function() {
                alert(self.tabArray[index]);
            };
        }
    }
    

    ......和as goreSplatter以及费利克斯指出,这一行:

    window.onload = init();
    

    ... 调用 init函数,并使用其返回值分配给onload。你的意思是:

    window.onload = init;
    

    ...只是将init分配给onload事件。


    偏离主题:您可以考虑使用较新的“DOM2”机制来附加事件处理程序,而不是使用onXYZ属性和属性的旧“DOM0”方式。新的方式称为addEventListener,尽管可悲的是Internet Explorer最近才添加(但它具有非常相似的attachEvent)。如果您使用的是jQueryPrototypeYUIClosureany of several others这样的库,他们会为您解决这些差异(并提供批量)其他有用的东西)。

答案 1 :(得分:4)

有问题的:

function init()
{
    tab = new Tabs('tab1','tab2','tab3','tab4');
    tab.setClickable();
}

window.onload = init();

在这种情况下,window.onload将为undefined,因为init()不返回任何内容。当然你的意思是

window.onload = init;