0
$(document).ready(function() {
            var spans = $("#divTest span");
            for (var i = 0; i < spans.length; i++) {
                spans[i].onclick = function() {
                    alert(i);
                }
            }
        });
        
<div id="divTest"><span>0</span><span>1</span>
<span>2</span><span>3</span></div>

我很纠结的是:为什么每个span点击的时候个弹出的i值都为length

5个回答

3

已采纳

点击的时候再去取i,此时i已经变成length

你看这个例子就懂了

<html>

<head>
    <title>closure</title>
</head>

<body>
    <button id="myBtn">click</button>
    <button id="myBtn2">i++</button>
</body>

<script>
    var element = document.getElementById("myBtn");
    var element2 = document.getElementById("myBtn2");
    var i = 0;
    element.addEventListener("click", function (e) {
        alert(i);
    });
    element2.addEventListener("click", function (e) {
        i++;
    });
</script>

</html>
3

i 是外部作用域的变量,onclick 的内部作用域可以使用它。但 i 在外面变化的时候,onclick 内部并不能锁定它的值。把这个作用域相似扩大来看,就像是全局变量在局域使用一样。 @熊丸子 的回答应该很清楚了。

边城 · 2015年09月06日

展开评论
2

这样写就可以了。

$(document).ready(function() {
    var spans = $("#divTest span");
    for (var i = 0; i < spans.length; i++) {
        ;(function(i){
            spans[i].onclick = function() {
                alert(i);
            }
        })(i);
    }
});

说一说为什么,因为页面加载完的时候,for循环也瞬间执行完了,点击的时候i早就变成了length,而且大家算是共享这一个i
但是为什么上面说的行呢,因为将i放到一个自动执行的闭包中,首先它会自动执行,然后实参传递到形参的时候,非引用类型的实参传递给形参会复制一份,而不是共享一份,所以就会有n个i了,每个i都不一样。

0

for循环下,spans1,2,3的click事件都被赋予了一个匿名函数 function () { alert(i) },这里的i显然在循环的时候已经不断的++了,但循环时并没有被调用,在点击事件发生,函数执行时才把i赋值的结果显现出来,你把alert(i)加在事件外部时,就可以看到i变化了

for (var i = 0; i < spans.length; i++) {
    alert(i) //实时调用
    spans[i].onclick = function() {
        alert(i); //事件(发生时)调用
    }
}
0

循环在前,你触发的click事件,所以当你执行click事件的时候,变量i开始根据作用域链开始找,但是循环已经结束了,它只能取到循环完的i值。

理解了上面一点,你就应该明白为什么用闭包的前提了。

然后你再去理解闭包

撰写答案