0
点赞
收藏
分享

微信扫一扫

浅谈JS执行时机与闭包

JS执行时机与闭包

简单来说,JS在执行代函数的时候,由于某些变量的值会改变,所以在不用的时间,不同位置执行函数结果可能会不一样,这就是所谓的执行时机

先看一个简单的例子

let num = 1;
function fn(){
    console.log(num);
}
fn();   //  1
num = 2;
fn();  //   2   

上面例子说明代码执按照一定的顺序,执行的时机绝对了结果

再看一个例子

for(var i = 0; i<6; i++){
    console.log(i);
}   //  0 1 2 3 4 5

for(var i = 0; i<6; i++){
    setTimeout(()=>{
     console.log(i);
  },0)
}  //   6 6 6 6 6 6    

//这里的setTimeout是等一会在执行,具体等多久取决于毫秒参数,但是即使是0,也是等代码执行完成后再来执行这里的代码,因此此时i已经是6了,所以会打出6个6

加下来看这段代码

let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}   //  6 6 6 6 6 6 

为什么打印出6个6呢?

注意此段代码用let声明的for循环的循环变量i是在全局作用域就定义好的,而setTimeout是等待别的代码执行完毕再执行里面的代码,因此会打印出6个6

要想打印出0 1 2 3 4 5 ,只需要把let声明的i写在for里面即可

for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}  //   0 1 2 3 4 5
// let 关键字与 for 循环配合使用会产生奇效,因为在每次循环中,JS会单独创建一个i变量保存在对应的{}作用域中,因此每次循环的值都会被保存下来以便使用,才会有 0 1 2 3 4 5 

那么问题来了,我要是非要使用 var 声明变量达到 let 的效果呢?

利用闭包

for(var i = 0; i < 6; i++){
     (function(i){    // 这里是立即执行函数
       setTimeout(function(){  
          console.log(i);  // 这里便属于用到了闭包
       },0) 
    })(i);
} // 0 1 2 3 4 5

浅谈闭包概念:简单来讲,如果一个函数内使用到了它外部作用域的变量,那么这个函数加上这个变量所构成的一个封闭的环境便是闭包

//   打飞机游戏场景
function begin(){   //  这个函数表示开始游戏
    let count = 0; // 表示打掉的飞机数量
  return function planeCount(){   // 这个函数表示打落飞机时增加打掉的飞机数量
        count++;                  // 把它返回出去,这样在外部就能改变局部变量count了
    }
}

let planeC = begin();  // 在外部用变量接收,同时游戏开始  

planeC();  //  每调用一次  飞机数量都加一  除此之外在外部无法改变count的值

由此可以看出闭包的应用简单来说就是隐藏或者是保存局部变量,因为一旦形成闭包,形成闭包的局部变量就不会被JS给垃圾回收掉,即它的值会保存,这是闭包的一个机制

举报

相关推荐

0 条评论