阅读 186

for循环+setTimeout遇到的问题(settimeout())

以下代码会打印5次5,而不会依次打印0~4:

for (var i = 0; i < 5; i++) {   setTimeout(() => {     console.log(i)   }, 1000) } 复制代码

image.png

原因:通过var声明的变量会发生变量提升。即等价于以下代码:

var i; // i为全局变量 for (i = 0; i < 5; i++) {   setTimeout(() => {     console.log(i)   }, 1000) } // 或者下面这样展示更直观 var i; // i为全局变量 for (i = 0; i < 5; i++) { } // i==5了 setTimeout(() => {   console.log(i) // 5 }, 1000) setTimeout(() => {   console.log(i) // 5 }, 1000) setTimeout(() => {   console.log(i) // 5 }, 1000) setTimeout(() => {   console.log(i) // 5 }, 1000) setTimeout(() => {   console.log(i) // 5 }, 1000) 复制代码

静态代码执行完时(i=5时跳出循环),全局变量i就已经变为5了。由于setTimeout要等静态代码执行完,即for循环执行完,且过了1s之后才会执行setTimeout。因此执行setTimeout时,传入的全局变量i的最终值:5。效果就是打印5次5。

解决方法:

方法1:给setTimeout封装到一个局部函数,每个局部函数都拥有一个独立的作用域,内部的变量会遮蔽全局作用域的同名变量,也不会受其他代码块的影响,俗称闭包

for (var i = 0; i < 5; i++) {   (     // 形参m由i赋值     function (m) {       setTimeout(() => {         console.log(m)       }, 1000);     }   )(i) } 复制代码

方法2:使用let或const关键词

for (let i = 0; i < 5; i++) {   setTimeout(() => {     console.log(i)   }, 1000) } 复制代码

方式3:块级作用域

for (var i = 0; i < 5; i++) {   {     // {}内添加一个let或const后,会成为块作用域     let j = i;     setTimeout(() => {       console.log(j);     }, 1000);   } } 复制代码

以上内容含自己的理解,仅用于自学记录。


作者:carryon
链接:https://juejin.cn/post/7038989303623450660

 伪原创工具 SEO网站优化  https://www.237it.com/ 


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐