search

Home  >  Q&A  >  body text

javascript - 创建了5个按钮,但是每个按钮点击后都会弹出5,不知道为什么??

for(var i =0;i<5;i++)
{
button = document.createElement("button");
button.innerHTML = "Button" + i;
document.body.appendChild(button);
button.addEventListener("click",function(e){alert(i);},false);
}
结果是创建了5个按钮,但是每个按钮点击后都会弹出5,不知道为什么??

我本以为这样也可以,希望点击的时候回触发函数x,但是每次创建一个按钮就会自动触发函数x???
for(var i =0;i<5;i++)
{function x(e){alert(e)}
button = document.createElement("button");
button.innerHTML = "Button" + i;
document.body.appendChild(button);
button.addEventListener("click",x(i),false);
}

大家讲道理大家讲道理2902 days ago239

reply all(4)I'll reply

  • 大家讲道理

    大家讲道理2017-04-10 17:12:27

    又是闭包的问题,总是见到人们问这个问题。自行百度就会有各种各样的答案。

    ES 5.1 只有函数作用域,不是说有个{} 就会创建一个新的作用。而是只有函数定义中的{}才能形成一级新的作用域。
    for 的 i 定义在全局,因此全局只定义了一个变量i。
    回调的那个匿名函数会形成一级新的作用域,但是其中没有定义变量 i。 因此,匿名函数中访问的 i 是全局的 i。而全局变量中只定义了一个 i,怎么可能不同的时候分别等于1,2,3,4,5

    for(var i =0;i<5;i++)
    {
    button = document.createElement("button");
    button.innerHTML = "Button" + i;
    document.body.appendChild(button);
    (function(){
        var j = i;
        button.addEventListener("click",function(e){alert(j)},false);
    })()
    }

    上述代码,在我的匿名函数执行的时候,会创建一个新的作用域,循环 5 次,所以会形成5 个不同的作用域中的j。每次循环创建一个作用域,而给 j 赋值的时候 i,i分别等于1,2,3,4,5,所以5个作用域中的j分别等于1,2,3,4,5。回调函数中的匿名函数也是分别在这5个不同作用域中,因此他们分别对应各自作用域中的j,所以可以得到 1,2,3,4,5;

    或者 HTML5

    for(let i =0;i<5;i++)
    {
    button = document.createElement("button");
    button.innerHTML = "Button" + i;
    document.body.appendChild(button);
    button.addEventListener("click",function(e){alert(i);},false);
    }

    let 的语法:
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 17:12:27

    i 不在 function (e) {} 这个作用域里,向上一直找到for 下面那级作用域,而这个i一直在++,for循环执行完毕i就是5

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 17:12:27

    最后i是5啊, 你想想

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-10 17:12:27

    循环执行完后,i的值最终被赋值为5,执行click事件的回调函数时,才会去作用域中查找i变量的值,自然就alert出5,因为ES5没有块级作用域,所以只能利用函数作用域,一个闭包的匿名函数自执行即可,分别创建单独的变量。

    for(var i =0;i<5;i++)
    {
    button = document.createElement("button");
    button.innerHTML = "Button" + i;
    document.body.appendChild(button);
    (function(i){button.addEventListener("click",function(e){alert(i);},false);})(i)
    }

    reply
    0
  • Cancelreply