【js】var 和 let 在 for 循环中的不同反应

for循环中var和let的不同

 在var里面:

代码对比:

//用var声明变量
for(var i = 0; i < 5; i++){
  setTimeout(()=>{
    console.log(i); // 5个5
  },100) 
}
console.log(i); // 5

for循环中对循环变量使用var声明,输出会产生错误的结果,与我们原本想输出的结果不同。

因为var是全局作用域,有变量提升的作用,所以在for中定义一个变量,全局可以使用,循环中的每一次给变量 i 赋值都是给全局变量 i 赋值,也就是说后面的赋值会覆盖前面的。

另外这也牵涉到异步。 在var里面:
setTimeout是异步执⾏,10ms后往任务队列⾥⾯添加⼀个任务,只有主线上的全部执⾏完,才会执⾏任务队列⾥的任务,当主线执⾏完成后,i 是 5,所以此时再去执⾏任务队列⾥的任务时,i 全部是5了。

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

相当于:

//用var声明变量
for(var i=0;i<5;i++){
  setTimeout(()=>{
    console.log(i);//5个5
  },100) 
}
//实际上是
var i=0;
var i=1;
var i=2;
var i=3;
var i=4;
setTimeout(()=>{
    console.log(i);
}

 在let里面:

//用let声明变量
for(let j = 0; j < 5; j++){
  setTimeout( ()=> {
    console.log(j);//0,1,2,3,4
  },100) 
}
console.log(j);//报错 j is not defined

let是块级作用域只能在代码块中起作用,在js中一个 { } 中的语句我们也称为叫一个代码块,每次循环会产生一个代码块,每个代码块中的都是一个新的变量 j ;

在let里面:因为for循环头部的let不仅将 i 绑定到for循环中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout 里面的 function( ) 属于一个新的域,通过 var 定义的变量会不断覆盖之前的值通过 let 定义的变量会产生块级作用域,后面赋值的变量不会改变前面的值,因为它们处于不同的块级作用域。

使用let声明变量
for(let j = 0; j < 5; j++){
  setTimeout(()=>{
    console.log(j);//0,1,2,3,4
  },100) 
}
//实际上就是
{let j=0;setTimeout()=>{...}}
{let j=1;setTimeout()=>{...}}
{let j=2;setTimeout()=>{...}}
{let j=3;setTimeout()=>{...}}
{let j=4;setTimeout()=>{...}}

let 和var的作用域区别

{
  let a=123;
}
{
  let a=456;
}
console.log(a);//a is not defined;

{ 
  var b=1;
}
{ 
  var b=2;
}
console.log(b);// 2;

{ } 代表一个块,这个时候 let 声明的变量只在这个块中起作用,而这个块对var声明的变量不起作用。因为var是全局作用域,不断给b赋值,后面b的值会覆盖前面的。而 let 只在当前作用域内有效。

let a = 1;
let a = 2;
//Uncaught SyntaxError: Identifier 'a' has already been declared
//let不能重复声明

let b = 1;
var b = 2;

// Uncaught SyntaxError: Identifier 'a' has already been declared
//let不能重复声明


var c = 3;
var c = 4;
console.log(c)//4;var可以重复声明


解决方案:

立即执行函数

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

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

            (function(i) {

                setTimeout(function timer() {

                    console.log(i);

                });

            })(i);   //0,1,2,3,4

      }

立即执行函数,每次循环都产生一个新的函数作用域每个函数作用域存着这次循环的结果
倒计时1秒后打印出每个函数作用域里面的值。

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值