首页 > 问一个JavaScript里弱弱的闭包的问题

问一个JavaScript里弱弱的闭包的问题

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>闭包</title>
</head>
<body>
<input type="button" id="id1" value="1"></input>
<input type="button" id="id2" value="2"></input>
<input type="button" id="id3" value="3"></input>
<input type="button" id="id4" value="4"></input>
<input type="button" id="id5" value="5"></input>
<input type="button" id="id6" value="6"></input>
<input type="button" id="id7" value="7"></input>
<input type="button" id="id8" value="8"></input>
<input type="button" id="id9" value="9"></input>
<input type="button" id="id10" value="10"></input>
<script type="text/javascript">
for (var i = 1; i <= 10; i++)
{
        console.log(i);//10
   document.getElementById("id"+i).onclick = function ()
    {
       console.log(i); 
        alert(i);
}  
}
</script>
</body>
</html>
    


----------
   不是很理解点击事件的触发过程。。。
  在外层for语句i=10,当进入内部函数的时候,i++,由于作用域,内部函数可以调用作用域链上外部的变量,所以内层输出为11。
  但外层输出了i=1/2/3/4/5/6/7/8/9/10,
我的疑惑是比如当点击第二个按钮的时候,外层的i已经循环到10了,按这种思路来说,是直接会触发:
document.getElementById("id10").onclick = function (){},意思是只有第10个按钮才会触发。。
第二个按钮为什么会触发onclick事件呢..
之前看到了外层会输出i=1/2/3/4/5/6/7/8/9/10,意思是都会触发吗?
能不能这样理解:
点击第二个按钮的时候,i=2,document.getElementById("id2").onclick = function (){},被触发的时候,但是for循环不会停止,当判断条件不为false的时候,则i=11也会传入document.getElementById("id2").onclick = function (){}
内部函数里,然后由于先后顺序,i=11会覆盖掉之前的i=2的赋值,最后输出11。。。是这样理解的吗??
像下面(这样的话,就只会输出一个值,而且只有当点击第五个按钮的时候):
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>闭包点击5</title>
</head>
<body>
<input type="button" id="id1" value="1"></input>
<input type="button" id="id2" value="2"></input>
<input type="button" id="id3" value="3"></input>
<input type="button" id="id4" value="4"></input>
<input type="button" id="id5" value="5"></input>
<input type="button" id="id6" value="6"></input>
<input type="button" id="id7" value="7"></input>
<input type="button" id="id8" value="8"></input>
<input type="button" id="id9" value="9"></input>
<input type="button" id="id10" value="10"></input>
<script type="text/javascript">
 var i=5;
   document.getElementById("id"+i).onclick = function ()
    {
       console.log(i); 
        alert(i);
}
</script>
</body>
</html>

对原理和顺序不是很了解。。。求解答。。万分感谢

1) js没有块级作用域,只有函数作用域;也就是说for循环中声明的变量的作用域不在for循环块中,其中声明的变量的作用域为其所在的函数或全局作用域
2) js函数中变量作用域是在函数声明的时候确定-词法作用域,也就是在函数声明的时候就确定函数中使用到的变量去哪里寻找
3)

for (var i = 1; i <= 10; i++)
{
   console.log(i);//10
   document.getElementById("id"+i).onclick = function (){
       console.log(i); 
        alert(i);
    }  
} 

for循环每次执行为对一个的DOM元素绑定了一个click事件回调函数,而这个绑定的匿名函数不会在for循环执行的时候执行,等到对应DOM元素上的click事件发生后才被执行
4) click匿名函数声明时,就确定函数中使用到的变量i在其所在函数的外层函数或全局作用域中
5)当click匿名函数执行时-click事件发生,i变量的值就为for循环结束后的值,为11


  1. for循环中你已经给所有input绑定了onclick事件,当然不管点击哪一个都能触发事件

  2. 函数内部不是i覆盖了原来的值。正确的理解是这样的,在绑定onclick事件的时候,仅仅只是定义了一个匿名函数,然后将这个匿名函数赋值给了input的onclick事件,和匿名函数内部是什么内容没有关系。
    然后在你点击input的时候,匿名函数被运行,逐行运行的时候,需要打印i的值,此时循环已经结束,i=11

  3. 下面这个你只绑定了id5,那当然只有点击id5才有反映

  4. 想要在上面的例子中保存i,你需要使用闭包,隔离作用域——

for (var i = 1; i <= 10; i++) {
    console.log(i);
    (function() {
        var index = i;
        document.getElementById("id"+index).onclick = function () {
            console.log(index); 
            alert(index);
        }  
    })();
}

或者,如果你使用了ES6,自带块级作用域的话,更简单一点

for (let i = 1; i <= 10; i++) {
    console.log(i);
    document.getElementById("id"+i).onclick = function () {
        console.log(i); 
        alert(i);
    }
}
【热门文章】
【热门文章】