目录
先来个简单的测试
for (var i = 0; i < but.length; i++) { console.log(i)//0 1 2 }
for (let i = 0; i < but.length; i++) { console.log(i)//0 1 2 }
会发现var和let作为循环的执行输出貌似没什么问题。
是不是就没有区别呢?
当然不是!
变量提升
- 相信很多人都知道var有变量提升的问题
- 我们猜想如果
var
导致i
提升了,那么用var
声明的i
会成为window全局的变量。
for (var i = 0; i < but.length; i++) { console.log(i)//0 1 2 }
代码就相当于i提升到了全局上,循环时用的都是同一个window.i的值
var i //window.i for (i = 0; i < but.length; i++) { console.log(i)//0 1 2 console.log(window.i)//0 1 2 } console.log(i)//3
我们可以做个对照,let声明的i拥有了自己的块级作用域,每次循环的i只在当前循环有效,第一次声明i=0、第二次i=1、。
for (let i = 0; i < but.length; i++) { console.log(i)// 0 1 2 console.log(window.i)//undefined undefined undefined } console.log(i)//undefined
问题场景
给按钮添加事件,我们希望按钮输出自己的下标值i和它的内容值。
结果是点击什么都是3,因为var声明的i不具备块级作用域,这里点击事件中的i读取不到这个for循环中的i,只能获取到window上的i,而这个i是最后的值,也就是跳出for循环的but.length,为3。
<body> <button>0</button> <button>1</button> <button>2</button> </body> <script> const but = document.getElementsByTagName('button') for (var i = 0; i < but.length; i++) { but[i].onclick = () => { console.log('点击的button的下标:' + i)//3 3 3 } } </script>
换成let试试
<body> <button>1</button> <button>2</button> <button>3</button> </body> <script> const but = document.getElementsByTagName('button') for (let i = 0; i < but.length; i++) { but[i].onclick = () => { console.log('点击的button的下标:' + i)//0 1 2 } } </script>