Javascript jquery事件绑定传递值

Javascript jquery事件绑定传递值,javascript,javascript-events,pass-by-value,jquery,Javascript,Javascript Events,Pass By Value,Jquery,下一页显示五个按钮,单击每个按钮将获得警报“5”。我想当我点击第一个按钮时,我会得到警报“1”,第二个按钮“2”…等等 <!doctype html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> </head> <bod

下一页显示五个按钮,单击每个按钮将获得警报“5”。我想当我点击第一个按钮时,我会得到警报“1”,第二个按钮“2”…等等

<!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
    </head>
    <body>
        <div id="nums"></div>
        <script type="text/javascript">
            var nums = [1,2,3,4,5];
            for(var i in nums){
                var num = nums[i];
                var btn=$('<button></button>').text(num).click(function(){alert(num);});
                $('#nums').append(btn);
            }
        </script>
    </body>
</html>

JavaScript只有函数作用域,所以在您的示例中只有一个num,它一直在被修改,在调用click事件时,它等于五。要解决此问题,必须使用新的函数作用域创建右侧,如下所示:

var nums = [1,2,3,4,5];
var createClick = function (num) { return function() { alert(num); }; };
for(var i in nums){
    var num = nums[i];
    var btn=$('<button></button>').text(num).click(createClick(num));
    $('#nums').append(btn);
}  
// jQuery will set 'this' for you when it calls your click handler
[...].click(function(){ alert($(this).text()); });

JavaScript只有函数作用域,所以在您的示例中只有一个num,它一直在被修改,在调用click事件时,它等于五。要解决此问题,必须使用新的函数作用域创建右侧,如下所示:

var nums = [1,2,3,4,5];
var createClick = function (num) { return function() { alert(num); }; };
for(var i in nums){
    var num = nums[i];
    var btn=$('<button></button>').text(num).click(createClick(num));
    $('#nums').append(btn);
}  
// jQuery will set 'this' for you when it calls your click handler
[...].click(function(){ alert($(this).text()); });
更改此行:

var btn=$('<button></button>').text(num).click(function(){alert($(this).text()});
更改此行:

var btn=$('<button></button>').text(num).click(function(){alert($(this).text()});

在循环中创建的事件处理程序函数对创建它们的范围内的变量有一个持久的引用,而不是创建函数时这些变量的副本。这就是闭包的工作原理:。因此,所有处理程序函数都引用相同的num变量,并且在单击事件发生时引用该变量。因为在这一点上,它是5,这是它被分配的最后一个值,所以最终它们都会向5发出警报

如果希望事件处理程序在创建处理程序时引用num,则必须让处理程序关闭一些不会更改的内容。通常的方法是使用一个构建处理程序函数的函数,并让处理程序函数关闭该构建器函数的参数:

var nums = [1,2,3,4,5];
for(var i in nums){
    var num = nums[i];
    var btn=$('<button></button>').text(num).click(buildHandler(num));
    $('#nums').append(btn);
}

function buildHandler(val) {
    return function(){alert(val);};
}
<script>
    (function() {
        var nums = [1,2,3,4,5];
        for(var i in nums){
            var num = nums[i];
            var btn=$('<button></button>').text(num).click(buildHandler(num));
            $('#nums').append(btn);
        }

        function buildHandler(val) {
            return function(){alert(val);};
        }
    })();
</script>
它做的事情与我们定义函数一样,然后立即调用它,但不创建全局i、num、nums和btn变量


非主题2:您使用了..in来处理数组,但没有进行任何检查以确保只处理数组索引。for..in不循环数组索引;它遍历对象属性名称。在循环中为..编写代码,就好像它们在数组索引中循环一样,会在某个阶段对您产生不利影响。只需使用普通for循环,或进行必要的检查,或使用jQuery函数。更多信息:

您在循环中创建的事件处理程序函数对创建它们的范围内的变量具有持久引用,而不是创建函数时这些变量的副本。这就是闭包的工作原理:。因此,所有处理程序函数都引用相同的num变量,并且在单击事件发生时引用该变量。因为在这一点上,它是5,这是它被分配的最后一个值,所以最终它们都会向5发出警报

如果希望事件处理程序在创建处理程序时引用num,则必须让处理程序关闭一些不会更改的内容。通常的方法是使用一个构建处理程序函数的函数,并让处理程序函数关闭该构建器函数的参数:

var nums = [1,2,3,4,5];
for(var i in nums){
    var num = nums[i];
    var btn=$('<button></button>').text(num).click(buildHandler(num));
    $('#nums').append(btn);
}

function buildHandler(val) {
    return function(){alert(val);};
}
<script>
    (function() {
        var nums = [1,2,3,4,5];
        for(var i in nums){
            var num = nums[i];
            var btn=$('<button></button>').text(num).click(buildHandler(num));
            $('#nums').append(btn);
        }

        function buildHandler(val) {
            return function(){alert(val);};
        }
    })();
</script>
它做的事情与我们定义函数一样,然后立即调用它,但不创建全局i、num、nums和btn变量

非主题2:您使用了..in来处理数组,但没有进行任何检查以确保只处理数组索引。for..in不循环数组索引;它遍历对象属性名称。在循环中为..编写代码,就好像它们在数组索引中循环一样,会在某个阶段对您产生不利影响。只需使用普通for循环,或进行必要的检查,或使用jQuery函数。更多信息:

您创建的所有单击处理程序都引用相同的全局变量num,在循环运行后,该变量将为5,在您实际单击以触发处理程序并显示警报时,该变量仍为5

有两种方法可以绕过,如下所示:

1如果您已经将数字设置为按钮的文本,请在处理程序中使用该数字,如下所示:

var nums = [1,2,3,4,5];
var createClick = function (num) { return function() { alert(num); }; };
for(var i in nums){
    var num = nums[i];
    var btn=$('<button></button>').text(num).click(createClick(num));
    $('#nums').append(btn);
}  
// jQuery will set 'this' for you when it calls your click handler
[...].click(function(){ alert($(this).text()); });
2创建一个闭包,以便为每个处理程序保留num的各个值:

[...].click((function(closureNum){
                return function(){ alert(closureNum); }
             })(num));
编辑:刚刚看到其他答案。为了更好地改变我的第二个选项,我建议像T.J.和FishBasketGordo那样,使用一个单独的处理程序构建函数,而不是像我那样内联执行。这两种方法都可以使用,但单独的处理程序生成器应该更高效,而且可以说更易于阅读。

您创建的所有单击处理程序都引用相同的全局变量num,在循环运行后为5,在实际单击触发处理程序并显示警报时仍为5

有两种方法可以绕过,如下所示:

1如果您已经将数字设置为按钮的文本,请在处理程序中使用该数字,如下所示:

var nums = [1,2,3,4,5];
var createClick = function (num) { return function() { alert(num); }; };
for(var i in nums){
    var num = nums[i];
    var btn=$('<button></button>').text(num).click(createClick(num));
    $('#nums').append(btn);
}  
// jQuery will set 'this' for you when it calls your click handler
[...].click(function(){ alert($(this).text()); });
2创建一个闭包,以便为每个处理程序保留num的各个值:

[...].click((function(closureNum){
                return function(){ alert(closureNum); }
             })(num));
编辑:刚刚看到其他答案。为了更好地改变我的第二个选项,我建议像T.J.和FishBasketGordo那样,使用一个单独的处理程序构建函数,而不是像我那样内联执行。两者都可以工作,但是单独的处理程序生成器应该可以 更高效,更容易阅读。

试试这个

<script type="text/javascript">
            var nums = [1,2,3,4,5];
            for(var i in nums){
                var num = nums[i];
                var btn=$('<button></button>').text(num).click(function(){alert(nums[i]);});
                $('#nums').append(btn);
            }
        </script>
试试这个

<script type="text/javascript">
            var nums = [1,2,3,4,5];
            for(var i in nums){
                var num = nums[i];
                var btn=$('<button></button>').text(num).click(function(){alert(nums[i]);});
                $('#nums').append(btn);
            }
        </script>
这更简单:

var nums = [1,2,3,4,5];
$.each(nums, function(index, value){
    var btn=$('<button></button>').text(value).click(function(){alert(value);});
    $('#nums').append(btn);
});
既然页面中已经有jquery,为什么不使用$.each?

这更简单:

var nums = [1,2,3,4,5];
$.each(nums, function(index, value){
    var btn=$('<button></button>').text(value).click(function(){alert(value);});
    $('#nums').append(btn);
});


既然页面中已经有jquery,为什么不使用$.each?

您的意思是,为了传递值,我必须创建一个闭包?为什么闭包可以允许按值传递?还有其他解决方案吗?这是一个常见问题。您已经在原始示例中创建了一个闭包,但是num引用了外部范围中的var num,当您在var num=nums[i]行中修改外部范围中的num时;,您正在修改闭包引用的num。因此,它总是向5发出警报。通过使用返回函数的helper函数,您可以围绕createClick的参数创建一个闭包,该参数不会被修改。这个解决方案有很多变化,但本质上都是一样的。JavaScript只有函数作用域。@彼得:这与按值传递无关。JavaScript完全是按值传递的;JavaScript中根本没有传递引用。你的意思是,为了传递值,我必须创建一个闭包吗?为什么闭包可以允许按值传递?还有其他解决方案吗?这是一个常见问题。您已经在原始示例中创建了一个闭包,但是num引用了外部范围中的var num,当您在var num=nums[i]行中修改外部范围中的num时;,您正在修改闭包引用的num。因此,它总是向5发出警报。通过使用返回函数的helper函数,您可以围绕createClick的参数创建一个闭包,该参数不会被修改。这个解决方案有很多变化,但本质上都是一样的。JavaScript只有函数作用域。@彼得:这与按值传递无关。JavaScript完全是按值传递的;JavaScript中根本没有传递引用。smart answer。但这是一种变通办法,而不是解决方案。文本恰好是我们想要提醒的;假设文本与我们想要提醒的内容无关,解决方法不起作用。对,但这不是问题。聪明的答案。但这是一种变通办法,而不是解决方案。文本恰好是我们想要提醒的;假设文本与我们想要提醒的内容无关,解决方法不起作用。对,但这不是问题。+1表示描述和链接文章中的for。我会说+2来奖励你写了这篇链接文章,但是对于详细的解释,我不会让我做+2.+1。我认为这个问题可以用另一种方式解决:1。deep clone num.alertnum.deep\u clone;但是我没有完成实验。我认为这个解决方案应该是可行的,至少在C和python等其他语言中是这样。@Peter:当单击触发时,您只需克隆num变量,这不会改变任何东西,您只需克隆值5即可。在循环创建处理程序的过程中,您必须更早地复制该值,这正是我们使用buildHandler所做的。对于for..in description和链接文章中的for..1。我会说+2来奖励你写了这篇链接文章,但是对于详细的解释,我不会让我做+2.+1。我认为这个问题可以用另一种方式解决:1。deep clone num.alertnum.deep\u clone;但是我没有完成实验。我认为这个解决方案应该是可行的,至少在C和python等其他语言中是这样。@Peter:当单击触发时,您只需克隆num变量,这不会改变任何东西,您只需克隆值5即可。在循环创建处理程序的过程中,您必须更早地复制该值,这正是我们使用buildHandler所做的。这不会起作用,原因与原始代码不起作用的原因相同:在循环运行之后,到实际调用处理程序时,我将是4岁。这与原始代码不起作用的原因是一样的:循环运行后,到实际调用处理程序时,我将是4岁。谢谢大家的精彩回答!我点击“+1”找到所有正确答案。但我只能接受一个答案。真的很抱歉。谢谢你们所有人的精彩回答!我点击“+1”找到所有正确答案。但我只能接受一个答案。真的很抱歉。