如何将'callbacks'数组参数传递给匿名函数?

时间:2013-10-16 21:22:46

标签: javascript jquery closures

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

...
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
},
....

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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)
        });
    };
},

...在创建函数时,对listi持久参考,而不是副本。由于i最终成为枚举的最后一个属性,因此所有处理程序最终都会引用相同的列表条目。

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

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调用的参数,而不是listi。由于entry(参数)不会改变,因此处理程序可以正常工作。

另请注意,我已将var self = this;移出循环,因为它不会因迭代而异,因此没有业务处于循环中。


旁注:您已经说过该函数会收到数组。如果是这样,for-in(没有安全措施)不是循环遍历该数组中条目的正确方法。更多:Myths and realities of for..in