闭包在循环事件绑定中的应用
- 场景描述:
在页面上有3个button按钮,当点击每个按钮时输出当前按钮的索引值,要求用循环来绑定每个按钮的事件,看下面的代码。
<button>button1</button>
<button>button2</button>
<button>button3</button>
var buttons = document.querySelectorAll('button');
for(var i = 0; i < buttons.length; i++){
buttons[i].onclick = function(){
console.log(`当前按钮的索引是${
{
i}`);
}
}
- 原因剖析
上述代码执行完成,发现并不是我们想要的效果,不管点击哪个按钮输出的都是3,而不是我们期望0,/1/2。那么代码看上去并没有问题,输出结果却为什么不是我们期望的呢?
- 这是因为每次for循环都只是开辟一块堆内存创建一个函数并将函数在堆内存中的地址赋值给每个button对象的属性onclick,这里并没有执行函数。
- 每循环一次i都会自动加1,直到i=3时循环结束。这时当我们点击某个按钮时才会去执行当前按钮的onclick属性所绑定的函数
- 函数执行时会形成一个私有上下文(作用域为全局上下文),在这个私有上下文中会用到变量i,但是该上下文中并不存在变量i,于是向上级上下文(也就是全局上下文)中查找,发现有变量i,但此时的i经过三次循环后值已经变成了3(