在事件触发器上将变量传递给闭包

Dan*_*iro 1 javascript closures functional-programming

我有一个循环,我为事件定义一个闭包:

for (var i = 0; i < 3; i++) {
    obj.onload = function(e) {
        me.myFunction(e, i);
    };
}
Run Code Online (Sandbox Code Playgroud)

我需要将该计数器变量传递给load触发事件时调用的函数.我总是得到相同的价值.

如何将正确的计数器值传递给函数?

T.J*_*der 5

解决这个问题的常用方法是使用构建器函数,以便处理程序关闭不会更改的内容:

function buildHandler(index) {
    return function(e) {
        me.myFunction(e, index);
    };
}
for (var i = 0; i < 3; i++) {
    obj.onload = buildHandler(i);
}
Run Code Online (Sandbox Code Playgroud)

你可以使用一个立即调用的函数表达式(IIFE)来做到这一点,但理论上它会在每个循环上创建并抛弃一个函数(我希望这些天大多数JavaScript引擎都能优化它)而且我至少认为它更难了阅读:

for (var i = 0; i < 3; i++) {
    obj.onload = (function(index) {
        return function(e) {
            me.myFunction(e, index);
        };
    })(i);
}
Run Code Online (Sandbox Code Playgroud)

这里有一个ES5功能,Function#bind,如果你想使用你可以使用me.myFunction直接,但你必须改变在您所期望的参数(顺序index第一,那么该事件):

for (var i = 0; i < 3; i++) {
    obj.onload = me.myFunction.bind(me, i);
}
Run Code Online (Sandbox Code Playgroud)

bind创建一个函数,在调用时,调用原始函数,this设置为第一个参数(me如上所述),然后调用任何进一步的参数,然后调用函数时使用的任何参数.(这就是为什么订单myFunction期望他们不得不改变index, e而不是e, i.)

在较旧的浏览器上,您需要一个垫片Function#bind.