对于循环功能,意外输出 - 始终相同

时间:2014-03-01 20:10:44

标签: javascript jquery loops

我有这种奇怪的情况,我不知道为什么输出不是我所期望的。这只是一个简单的for-loop函数。有人可以解释一下为什么会这样吗?

var pm = 2; 
for (var i = 0; i < pm; i++) {
     $("#specialty_pm_"+i).mouseenter(function(){
            alert(i);
    });
};

我的html中有2个div,它有id="specialty_pm_<?php echo $countPM; ?>",而div在php中的for循环函数中。 foreach ($employee_info as $emp_info){ $countPM++; } 我希望第一个div中悬停的警报为“1”,第二个div为“2”。但当我悬停第一个div时,它会发出“2”警告。

4 个答案:

答案 0 :(得分:3)

你应该使用JavaScript闭包:

var pm = 2; 
for (var i = 0; i < pm; i++) {
    var func = (function(i){
        return function(){
            alert(i);
        }
    })(i);
    $("#specialty_pm_"+i).mouseenter(func);
};

关键在于您的代码中所有mouseenter函数都使用相同的变量i,并且在循环结束后,它的最后一个值为2。使用范围链,嵌套函数及其在JavaScript中的闭包,您可以为变量创建安全范围。基本上嵌套函数的作用是为内部函数提供外部LexicalEnvironment。您可以在这篇文章中找到更多信息:

Scope Chain in Javascript

答案 1 :(得分:2)

您的警报无法正常工作,因为i只有一个实例。 在这种情况下,您可以在div中检查变量i。

试试这个:

$("#specialty_pm_"+i).mouseenter(function(){
     var id = $(this).attr('id');
     alert(id.substring(0,13));
});

答案 2 :(得分:1)

正如已经提到的那样,原因是i的范围对于两个事件处理程序都是相同的,因此它们将具有相同的值。

这个问题有几个解决方案。

解决方案1:通过即时功能创建新范围

var pm = 2; 
for (var i = 0; i < pm; i++) {
     $("#specialty_pm_"+i).mouseenter(function(instance){
        return function() {  alert(instance); };
    }(i));
};

你可以在这里看到它的一个小提琴:http://jsfiddle.net/LP6ZQ/

解决方案2:使用jQuerys data方法存储值

var pm = 2; 
for (var i = 0; i < pm; i++) {
     $("#specialty_pm_"+i).data('instance',i).mouseenter(function(){
            alert($(this).data('instance'));
    });
};

你可以在这里看到它的一个小提琴:http://jsfiddle.net/LP6ZQ/1/

解决方案3:bind事件编号到事件处理程序

var pm = 2; 
for (var i = 0; i < pm; i++) {
     $("#specialty_pm_"+i).mouseenter(function(instance){
        alert(instance);
    }.bind(null,i));
};

你可以在这里看到它的一个小提琴:http://jsfiddle.net/LP6ZQ/2/

解决方案3有一些注意事项 - this被绑定为null,因此它不能再用作dom元素的引用,就像jQuery eventhandlers一样。旧浏览器也不支持bind,但可以使用polyfill来减轻这种情况,可在此处找到一个好的:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

解决方案4:要聪明并使用委托而不是在循环中绑定事件处理程序

     $(document.body).on('mouseenter','.specialty_pm',function(){
        alert($(this).data('id'));
    });

你可以在这里看到它的一个小提琴:http://jsfiddle.net/LP6ZQ/4/

解决方案4是正确的方式&#34;要做到这一点,但它需要你改变你建立标记的方式

答案 3 :(得分:0)

您可以摆脱JavaScript中的for循环,并使用jQuery's Starts With Selector选择id'specialty_pm_'开头的所有元素

$("[id^='specialty_pm_']").on("mouseenter",function(){
     var id = $(this).attr('id');
     alert(id.substring(13));
});

E.G:http://jsfiddle.net/6bTJ3/

或者,您可以为每个class项添加specialty_pm_[n],以便在jQuery中更简单地选择它们。