简体   繁体   English

将带有参数的函数作为参数传递给jQuery的回调

[英]Passing function with parameters as a parameter to a jQuery's callback

I'm having some difficulties with passing functions around. 我在传递函数时遇到一些困难。 I have this code: 我有以下代码:

  var options = [
        { name: "menu 1", func: function (element) { $(element).css("color", "Red"); } },
        { name: "menu 2", func: function (element) { alert("menu 2"); } },
        { name: "menu 3", func: function (element) { alert("menu 3"); } }
    ];

        // This basically creates a div with ul, and li element for each object in options, 
        // and attaches click event to each li that should fire provided func. 
        (function menuMaker(options) {
            var menuDiv = $("<div id='test' />");
            var menuUl = $("<ul>");
            menuDiv.append(menuUl);

            for (var i = 0; i < options.length; i++) {
                var li = $("<li>" + options[i].name + "</li>");
                // **li.click(function () { options[i].func(menuDiv); });**  
                //>> The line above gives "options[i] is undefined" error. Looks like a scoping issue.

                var userFunc = options[i].func;
                **li.click(function(){ userFunc(menuDiv);});**  
                //>> The line above always fires the last function (alert("menu 3"))

                menuUl.append(li);
            }
            $(document.body).append(menuDiv);
        })(options);

and I'm getting those errors I've commented. 我收到了我已评论的错误。 Any ideas what am I doing wrong ? 有什么想法我做错了吗?

Thanks ! 谢谢 !

Classic example of misunderstanding closures. 误解关闭的经典示例。 See how to fix this here . 在此处了解如何解决此问题

The problem is indeed a scoping one. 这个问题确实是一个范围界定的问题。 The for loop does not create a new scope, so you have to create one inside it like: for循环不会创建新的作用域,因此您必须在其中创建一个新作用域,例如:

for (var i=0; i<10; i++) {
    (function(i) {
        // "i" will be local here, and be accessible 
        // form any function defined inside this closure
    })(i);
}

Try this, which iterates over the array adding <li> elements. 试试这个,它遍历添加<li>元素的数组。 The function to be called is assigned to the local 'func' variable and then used within the click handler function. 要调用的函数被分配给本地“ func”变量,然后在点击处理函数中使用。

$.each(options, function() {
    var func = this.func;

    menuUl.append(
        $('<li>').text(this.name).click(function () {
            func(menuDiv);
        })
    );
});

Remove the "options" argument from "(function menuMaker(options) { ". The options variable is already set outside of the function. By adding it as an argument the function looks for the argument of "options" and not the predefined variable of options. 从“(function menuMaker(options){”中删除“ options”参数。options变量已经在函数外部设置。通过将其添加为参数,该函数将查找“ options”的参数,而不是选项。

Im not great at explaining stuff, but as for passing the function through the for loop and to each individual click event, create an empty function like below, that way it doesnt reference the last value used. 我不太擅长于说明内容,但是对于将函数传递给for循环并传递给每个单独的click事件,请按如下所示创建一个空函数,这样它就不会引用最后使用的值。

Tested! 经测试! Works! 作品!

var options = [
    { name: "menu 1", func: function (element) { $(element).css("color", "Red"); } },
    { name: "menu 2", func: function (element) { alert("menu 2"); } },
    { name: "menu 3", func: function (element) { alert("menu 3"); } }
];

(function menuMaker() {
    var menuDiv = $('<div id="test" />'),
        menuUl  = $('<ul />').appendTo(menuDiv);

    for (var i=0; i<options.length; i++) {

        (function() {
            var func = options[i].func;
            $('<li>' + options[i].name + '</li>')
            .click(function(){ func(menuDiv); })
            .appendTo(menuUl);        
        })();

    }

    $(document.body).append(menuDiv);
})();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM