Javascript关闭冻结增量值的值

时间:2013-07-22 22:26:29

标签: javascript jquery closures

我很难理解并使用闭包(是的,我已阅读How do JavaScript closures work?

我的问题如下:

for (row = 0; row < 10; row++) {
    for (column = 0; column < 10; column++) {

        var target = $("#" + Data.Row[row].Column[column].ID);

        target.mouseenter(function () {
            var position = CalculatePosition($(this));

            alert("row:" + row + ",column:" + column);

            ...
        });
    }
}

正如您所料,只要目标将鼠标悬停在其上,行和列始终为9。我的问题是,如何冻结行和列的值,以便mouseevent匿名函数可以获得其预期值?我尝试过像

这样的事情
target.mouseenter(function() {}.bind(column));

这似乎适用于专栏,但当然this不再是指目标。

2 个答案:

答案 0 :(得分:5)

这里最简单的选择通常是定义一个返回处理程序的函数:

function getHandler(row, column)
    return function () {
        var position = CalculatePosition($(this));
        alert("row:" + row + ",column:" + column);
        // ...
    };
}

然后在循环中调用此函数以使处理程序在调用时将相关变量“固定”为其值:

for (row = 0; row < 10; row++) {
    for (column = 0; column < 10; column++) {
        var target = $("#" + Data.Row[row].Column[column].ID);
        target.mouseenter(getHandler(row, column));
    }
}

你也可以在循环中,在一个立即执行的匿名函数中执行此操作:

for (row = 0; row < 10; row++) {
    for (column = 0; column < 10; column++) {
        var target = $("#" + Data.Row[row].Column[column].ID);
        target.mouseenter((function(row, column) {
            return function () {
                var position = CalculatePosition($(this));

                alert("row:" + row + ",column:" + column);

                ...
            };
        })(row, column)));
    }
}

但IMO更加丑陋,难以阅读。

在任何一种情况下,这里的基本方法是建立一个新的函数作用域,使用循环变量作为参数;现在,当您在处理程序回调中使用它们时,它们不再引用外部作用域变量。

答案 1 :(得分:0)

你可以这样使用bind(第一个参数是上下文(this arg)):

target.mouseenter(function(row, column){
    ...
}.bind(target[0], row, column));

但是bind不是跨浏览器,你已经在使用jQuery了,所以你应该使用proxy代替:

target.mouseenter($.proxy(function(row, column){
    ...
}, target[0], row, column));