先看一个经典闭包问题:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
window.onload = function () {
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function (){
alert(i)
}
}
} // 点击结果都为4
为使输出内容为0,1,2,3.通常我们会使用立即执行函数来解决,如:
window.onload = function () {
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = (function (){
var index=i;
return function(){
alert(index)
}
}())
}
} // 点击结果为0,1,2,3
但是,使用let就可以轻松解决次问题(将for循环里的var改为let)
window.onload = function () {
var lis = document.getElementsByTagName('li');
// 将for里的var改为let
for (let i = 0; i < lis.length; i++) {
lis[i].onclick = function (){
alert(i)
}
}
} // 点击结果为0,1,2,3
为什么let可以解决闭包?
var声明的变量,在全局范围内都有效,所以全局只有一个变量i
。每一次循环,变量i
的值都会发生改变。
let声明的变量,仅在块级作用域内有效,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。而JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。