let和var在for循環中的不同表現


var聲明變量:

var只有函數作用域,沒有塊級作用域

//函數作用域的表現
function test(){
    var i =10;
    console.log(i); //10
}
test(); //10
console.log(i); // i is not defined;


//塊級作用域對var沒有約束
{
    var i = 10;
    console.log(i); //10
}
console.log(i); //10

從上面的代碼可了解到,塊級作用域對var是沒有約束作用的。

 

let聲明變量:

let與var不同,let是有塊級作用域的。

//塊級作用域對let聲明的變量有約束
{
    let i = 10;
    console.log(i); //10
}
console.log(i) //ReferenceError

 

了解了上面的特性再來看看,var和let在for循環的一些不同表現:

//var聲明i
function test(){
    for(var i=0;i<2;i++){
        setTimeout(()=>{
            console.log(i);
        },0);
    }
}
test();
//輸出結果:2、2

//let聲明i
function test(){
    for(let i=0;i<2;i++){
        setTimeout(()=>{
            console.log(i);
        },0);
    }
}
test();
//輸出結果:0、1

可以看到只是聲明方式不一樣,輸出的結果卻有很大的差異。

在此之前還需要了解setTimeout()的執行機制:

setTimeout()是以異步的方式執行的。在執行for循環的時候,並不是執行一次for循環就立刻執行一次setTimeout(),而會讓setTimeout()進入另一條線程進行等待,當主線程(這里就是test())執行完后,setTimeout()再依次執行。

 

在var中執行的時候:

因為var是沒有塊級作用域的,所以在for循環中聲明的i會存在於test()函數作用域中。每一次for循環就會聲明一次i,但后面聲明的變量會覆蓋前面聲明的變量。所以當for循環執行完后(此時setTimeout()還未被執行),函數作用域中的i的值就變成2了

而setTimeout()所在的線程中是這樣的:

//第一次進棧
setTimeout(()=>{
   console.log(i); 
});

//第二次進棧
setTimeout(()=>{
   console.log(i); 
});

這里的i都指向函數作用域中的i。所以輸出都為2。

 

在let中執行的時候:

因為塊級作用域的原因,let聲明的i都會存在於for塊級作用域中,每一次for循環都會生成一個塊級作用域。所以setTimeout()在線程中是這樣的:

{
  let i=0;
  setTimeout(()=>{
   console.log(i); 
  });    
}

{
  let i=1;
  setTimeout(()=>{
   console.log(i); 
  });    
}

所以會一次輸出0,1;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM