我在对象中有一个成员函数,它获取回调函数的数组以及为其设置此函数的事件的名称:
...
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
},
....
但出了点问题 - 对于所有事件,处理程序是最后一个设置的回调函数......
答案 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)
});
};
},
...在创建函数时,对list
和i
有持久参考,而不是副本。由于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
调用的参数,而不是list
和i
。由于entry
(参数)不会改变,因此处理程序可以正常工作。
另请注意,我已将var self = this;
移出循环,因为它不会因迭代而异,因此没有业务处于循环中。
旁注:您已经说过该函数会收到数组。如果是这样,for-in
(没有安全措施)不是循环遍历该数组中条目的正确方法。更多:Myths and realities of for..in