5

我知道this在事件处理函数中将值更改为接收事件的元素非常有用。但是,我想让我的函数总是在我的应用程序上下文中调用,而不是在元素上下文中。这样,我可以将它们用作事件处理程序以及以其他方式(例如在setTimeout调用中)。

所以,像这样的代码:

window.app = (function () {
    var that = {
        millerTime: function () {},
        changeEl: function (el) {
            el = el || this;
            // rest of code...
            that.millerTime();
        }
    };
    return that;
}());

可能是这样的:

window.app = (function () {
    return {
        millerTime: function () {},
        changeEl: function (el) {
            // rest of code...
            this.millerTime();
        }
    };
}());

第一种方式让我看起来很困惑。有没有一种简单的方法可以将接收事件的元素作为第一个参数(最好是 jQuery 包装的元素)传递给我的事件处理函数并在 的上下文中调用app?假设我使用 jQuery 绑定了一堆事件处理程序。我不想一直包含匿名函数:

$('body').on('click', function (event) {
    app.changeEl.call(app, $(this), event);  // would be nice to get event too
});

我需要一个函数来为我处理这一切。在这一点上,我觉得传递匿名函数是没有办法的,但我只是想看看是否有人有解决方案。

我的尝试:

function overrideContext (event, fn) {
   if (!(this instanceof HTMLElement) ||
         typeof event === 'undefined'
   ) {
       return overrideContext;
   }

   // at this point we know jQuery called this function // ??
   var el = $(this);

   fn.call(app, el, event);
}

$('body').on('click', overrideContext(undefined, app.changeEl));

编辑: 使用Function.prototype.bind(我是新手),我仍然无法获得元素:

window.app = (function () {
    return {
         millerTime: function () {},
         changeEl: function (el) {
            // rest of code...
            console.log(this); // app
            this.millerTime();
         }
    };
}());

function overrideContext (evt, fn) {
    var el = $(this); // $(Window)
    console.log(arguments); // [undefined, app.changeEl, p.Event] 
    fn.call(app, el, event);
}

$('body').on('click', overrideContext.bind(null, undefined, app.changeEl));

$('body').on('click', overrideContext.bind(app.changeEl));相反,使用this指向我的app.changeEl函数,我的参数长度为 1 并且仅包含p.Event. 在这两种情况下,我仍然无法获取元素。

4

2 回答 2

3

您可以使用Function.prototype.bind.

$('body').on('click', overrideContext.bind(null, undefined, app.changeEl));

您也可以传入实际element作为方法的上下文

$('body').on('click', overrideContext.bind(app.changeEl));
于 2012-12-30T00:38:35.627 回答
0

我相信你的错误是试图控制哪些参数将传递给事件处理程序。如果您真的非常想要,您必须创建自己的事件处理实用程序,就像 jQuery 一样,并手动调用处理程序,传递您想要的任何参数作为参数。

但是,你真的需要吗?如果您依赖于附加的常规处理程序addEventListener,或者附加有 jQuery 中可用的各种方法之一的处理程序,您将始终将event对象作为第一个参数。并且触发事件的元素将始终在event.target.

考虑到这一点,您可以Function.prototype.bind像 jAndy 建议的那样使用 来设置this您想要的任何值。

于 2013-01-04T16:51:53.420 回答