0

我在对象中有一个成员函数,它获取回调函数数组和为其设置此函数的事件的名称:

...
setHandlesByList: function (list) {
    for (var i in list) {
        var self = this;
        $(document).on(list[i].name, function (e) {
            list[i].callBack.call(self,e)
        });
    };
},
...

在子对象的某个地方,我调用了父对象的这个函数:

...
initClass: function () {
    this.setHandlesByList([
     { name: 'configChecked', callBack: onConfigChecked },
     { name: 'configExpired', callBack: onConfigExpired },
    ]);
},
onConfigChecked: function() {
    // some code
},
onConfigExpired: function() {
    // some code
},
....

但是出了点问题-对于所有事件,处理程序都是最后设置的回调函数...

4

2 回答 2

3

尝试以下操作:

setHandlesByList: function (list) {
    for ( var i = 0; i < list.length; i++ ) {
        addCallback(list[i].name, list[i].callback);
    }
    function addCallback(on, name, callback) {
        $(document).on(name, function(e) { callback.call(on, e); });
    }
},

您的范围界定存在问题,因为最终的值i最终成为i评估回调时的最后一个值。

另请注意,您可以使用list.forEach.

于 2013-10-16T21:31:36.067 回答
2

您在此代码中创建的每个事件处理函数:

setHandlesByList: function (list) {
    for (var i in list) {
    var self = this;
    $(document).on(list[i].name, function (e) {
        list[i].callBack.call(self,e)
        });
    };
},

...具有对 and 的持久引用,而不是在创建函数时它们的副本。由于最终是枚举的最后一个属性,因此所有处理程序最终都引用相同的列表条目。listii

相反,创建一个构建器函数来创建回调(抱歉,我无法重新创建您使用的缩进样式,我只是使用了一个相当标准的缩进样式)

setHandlesByList: function (list) {
    var self = this;

    for (var i in list) {
        $(document).on(list[i].name, buildHandler(list[i]));
    };

    function buildHandler(entry) {
        return function (e) {
            entry.callBack.call(self,e)
        };
    }
},

现在,创建的函数关闭了调用entry的参数buildHandler,而不是结束了listand i。由于entry(参数)没有改变,处理程序工作。

另请注意,我已将var self = this;循环移出,因为它在迭代之间没有变化,因此没有业务在循环中。


旁注:您已经说过该函数接收一个数组。如果是这样,for-in(没有保护措施)不是循环遍历该数组中的条目的正确方法。更多:神话和现实for..in

于 2013-10-16T21:30:22.233 回答