变量提升
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>
待续。。。