1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>Document</title> 9 </head> 10 11 <body> 12 <script> 13 //先看一個例子 14 15 // var a = 1 16 // function fn() { 17 // console.log(a); 18 // var a = 3 19 // } 20 // fn() 21 22 /* 23 上述的例子返回的是undefined,這就是由於變量提升導致的。當我們通過var聲明了一個變量的時候 24 會同時生成一個執行環境,當我們在函數外部聲明的變量,就會生成一個全局執行環境,在函數內部聲明的 25 變量,會生成一個局部執行環境。執行環境的生成又會有兩個階段,第一階段是創建階段,這一階段js會將變量名提升 26 並在內存中開辟一個空間來存儲變量,並將它賦值為undefined;第二階段是執行階段,這一階段js會將值賦給變量 27 並執行代碼。 28 因此,上述代碼實際是下面這樣的: 29 */ 30 // var a = 1 31 // function fn(){ 32 // var a // 局部環境中聲明的變量會覆蓋掉全局環境中聲明的變量 33 // console.log(a); 34 // a = 3 35 // } 36 // fn() 37 38 /* 39 在使用var聲明變量的時候,會經常導致因為變量名提升導致的錯誤。使用var在局部環境中聲明的變量會覆蓋掉全局環境 40 中聲明的變量。因此,在es6中提出了let和const來創建塊級作用域,保證了變量不會被外部環境中的變量干擾污染 41 */ 42 // 再看下面這個例子: 43 for(var i=0;i<5;i++){ 44 setTimeout(function(){ 45 console.log(i); // 5,5,5,5,5 46 },1000) 47 } 48 /* 49 上述例子中,通常會認為打印出0,1,2,3,但實際上打印出的是5,5,5,5,5;這是有setTimeout是異步執行的 50 當js執行代碼的時候,會將異步任務暫且放在任務隊列中,當棧中的任務全部結束后,再從任務隊列中將需要執行的 51 的任務放到執行棧中去執行,因此上述代碼會先執行5次for循環,當循環執行完畢后,這時候在執行setTimeout函數, 52 此時的i已經是5,但是setTimeou還需要執行5次,就打印了5個5。 53 那么如何讓上述代碼執行的結果使我們需要的,將var改成let即可: 54 */ 55 for(let i=0;i<5;i++){ 56 setTimeout(function(){ 57 console.log(i);//0,1,2,3,4 58 },1000) 59 } 60 61 </script> 62 </body> 63 64 </html>
。。。