定义为HTML属性的事件句柄的作用域

今天在做项目的过程中,为了绑定事件方便,采用将事件句柄定义为HTML属性的方式来绑定事件。一开始是这个样子的:

HTML

<a href="javascript:;" onclick="action.removeTr(this)">Remove</a>

JS

    var action = {};
        window.action = action;
        action.removeTr = function(ele){
                $(ele).parent().parent().remove();
        };

我为什么这样写呢,因为我不想将太多的事件句柄直接放到window作用域中去,以免事件太多了,容易冲突,也不方便管理。于是我把HTML属性事件全都放到对象action里面去,然后再将此对象扩展到window里。这应该算是一个不错的想法,我之前也这样做过,都没问题的,但今天情况有所不同。总是报错:action.removeTr is not a function。

经过我不懈的努力!我找到了应外一种结局此问题的方法。有些非主流..(虽然后来我用了其他方法,但我还是不明白这种方法为什么能行)

JS

    setTimeout(function(){
                var action = {};
                window.action = action;
                action.removeTr = function(ele){
                        $(ele).parent().parent().remove();
                };
        }, 10000);

我只是让刚才那段代码延时执行了一会,注:这段代码是放在jQuery的document.ready函数中执行的哦!

太诡异了!!

不过我还不死心,就拿出《JavaScript权威指南》随手翻翻,希望能找到答案,果然没让我失望。P397有关于事件句柄作用域的章节。

定义为HTML属性的事件句柄 拥有与其它函数不同的作用域链。它的作用域链的头是调用对象(这意味着this指向该元素),并且事件句柄的作用域链中的下一个对象仍不是window,事件句柄的作用域会随定义句柄的对象终止,它还会延伸到包容层级,而且至少包括包含该元素的HTML<form>元素和包含表单的Document对象。作用域链终止对象才是window。

这就找到我之前出错的原因了,因为我的<a>标签是包含在表单之中的,onclick中的代码所访问的action对象不是我定义在window中的,而是表单的form.action。所以报错action.removeTr is not a function,因为form.action根本就没有removeTr这个函数。正确的写法只要该改个名字就可以了。

    var customAction = {};
        window.customAction = customAction;
        customAction.removeTr = function(ele){
                $(ele).parent().parent().remove();
        };