Closure needed for binding event handlers within a

2019-01-26 21:04发布

问题:

I'm trying to bind event handlers within a loop such as:

        var tabs = ['one', 'two', 'three', 'four']

        for(var i = 0; i < tabs.length; i++) {
            alert(tabs[i]);
            var id = i;
            $('#' + tabs[i]).bind('click', function() {
               loadTabs(id, tabs);
            });
        }

Which only keeps the last one bound (value 'four').

I'm trying to consolidate this code which currently does work:

        $('#one').click(function() {
            loadTabs(0, tabs);
        });

        $('#two').click(function() {
            loadTabs(1, tabs);
        });

        $('#three').click(function() {
            loadTabs(2, tabs);
        });

        $('#four').click(function() {
            loadTabs(3, tabs);
        });

Thought I might need a closure due to this post.

回答1:

You are right about what you read in the other post. You need to make a closure to bind the arguments to each single onclick handler:

$('#' + tabs[i]).bind(
    'click', 
    (function(id) {
        return function() 
        {
            loadTabs(id, tabs);
        };
    })(id)
);

You might also want to look into currying. In this example you might create a small helper function, which binds the first argument to a passed function and returns the new function.

function curry(func, arg1)
{
    return function()
    {
        func(arg);
    };
}

And then put it together like this:

$('#' + tabs[i]).bind(
    'click', 
    curry(function(id) { loadTabs(id); }, id)
);

Note that my curry function does not match the definition of currying, because it ignores any other argument. But it should work for your case.



回答2:

As you are already using jQuery you can use jQuery.each for this task. Therefor you won't need to do it yourself with, as you correctly assumed, closures.

var tabs = ['one', 'two', 'three', 'four'];

$.each(tabs, function(idx, tab) {
    $("#" + tab).on("click", function() {
        alert(idx);
        //loadTabs(idx, tabs);
    })
});

jsfiddle