for循环中var和let的区别

今天在做题的时候,遇到了一个不太懂的问题,经过查阅资料,终于搞明白了这个问题,发出来当做个笔记。

首先是var:

for (var i = 0; i < 5; i++) {

            setTimeout(function() {

                console.log(i);

            })

        };

输出结果:

let方法:

 for (let i = 0; i < 5; i++) {

            setTimeout(function() {

                console.log(i);

            })

        };

输出结果:

可以看到,var方法输出结果为5个5,let方法输出结果为01234,那么为什么会出现这种情况呢,主要原因就是因为setTimeout是异步执行的。

首先我们来了解下let和var的区别:

        然后这道题涉及到了异步,作用域还有闭包。

        在var里面:

        setTimeout是异步执⾏,10ms后往任务队列⾥⾯添加⼀个任务,只有主线线上的全部执⾏完,才会执⾏任务队列⾥的任务,当主线执⾏完成后,i是5,所以此时再去执⾏任务队列⾥的任务时,i全部是5了。对于打印5次是:

         每⼀次for循环的时候,settimeout都执⾏⼀次,但是⾥⾯的函数没有被执⾏,⽽是被放到了任务队列⾥⾯,等待执⾏,for循环了5次,就放了5次,当主线程执行完成后,才进入任务队列里面执行。

        在let里面:

        因为for循环头部的let不仅将i绑定到for循环中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的function()属于一个新的域,通过var定义的变量是无法传入到这个函数执行域中的,通过使用let来声明块变量能作用于这个块,所以function就能使用i这个变量了。

        注意:

        由于var命令的变量提升机制,var命令实际只会执行一次,而let命令不存在变量提升,所以每次循环都会执行一次,声明一个新变量(但初始化的值不同),for的每次循环都是不同的块级作用域,let声明的变量也是块级作用域,所以也不存在重复声明的问题,let声明变量的for循环里,每个匿名函数实际上引用的都是一个新的变量。

        当然,如果要使用var当做循环循环头的话,出现循环后打印出的结果一模一样的问题,可以使用闭包来解决。

 for (var i = 0; i < 5; i++) {

            (function(i) {

                setTimeout(function timer() {

                    console.log(i);

                });

            })(i);

        }

输出结果:

        通过闭包,将i的变量驻留在内存中,当输出i时,引用的是外部函数的变量值i,i的值是根据循环来的,执行setTimeout时已经确定了里面的的输出了。 

  • 18
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值