闭包典型-for循环

一、闭包的概念

  • 闭包就是有权访问另一个函数作用域中变量的函数,闭包的主要存在形式就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量

二、for循环按顺序顺出

  • for (var i = 0; i < 5; i++) {
      setTimeout(() => {
        console.log(i);
      }, 1000);
    }

    执行结果:输出五个5

        

        解析:for循环的时候,你并没有执行这个函数,你这个函数是过一秒才执行的,当执行这个函数的时候,

                   它发现它自己没有这个变量i,于是向它的作用域链中查找这个变量i,因为这个时候已经for循环完了,
                   所以储存在作用域链里面的i的值就是5,最后就打印出来5了。
  • 如何按顺序打印索引呢?
    • 使用let
      for (let i = 0; i < 5; i++) {
        setTimeout(() => {
          console.log(i);
        }, 1000);
      }
      //等价于
      // for (let i = 0; i < 5; i++) {
      //   let index = i;
      //   setTimeout(() => {
      //     console.log(index);
      //   }, 1000);
      // }

                     执行结果:

                     

                     解析:

                             利用 let 变量的特性 — 在每一次 for 循环的过程中,let 声明的变量会在当前的块级作用域里面
                           (for 循环的 body 体,也即两个花括号之间的内容区域)创建一个文法环境(Lexical Environment),
                             该环境里面包括了当前 for 循环过程中的 i
    •  自执行函数
      // for (var i = 0; i < 5; i++) {
      //   (function (i) {
      //     setTimeout(() => {
      //       console.log(i);
      //     }, 1000);
      //   })(i);
      // }
      //等价于  因为你在循环变量i的时候已经执行了函数,自然变量i是什么就打印出来什么
      for (var i = 0; i < 5; i++) {
        function temp(i) {
          setTimeout(() => {
            console.log(i);
          }, 1000);
        }
        temp(i);
      }

      执行结果:

                   

                     解析:

                              利用函数自执行的方式,把当前 for 循环过程中的 i 传递进去,变量i保存到这个自执行函数构建出的块级作用域中,IIFE 其实并不属于闭包的范畴
    • 使用定时器的第三个参数
      for (var i = 0; i < 5; i++) {
        setTimeout(
          (i) => {
            console.log(i);
          },
          1000,
          i
        );
      }

      执行结果:

                   

                     解析:

                               利用 setTimeout 函数的第三个参数,会作为回调函数的第一个参数传入     

三、for循环中每隔一秒打印一次   0  1  2  3   4  5

  • es5的方法:1000*i是重点
    for (var i = 0; i < 5; i++) {
      (function (i) {
        setTimeout(() => {
          console.log(i);
        }, 1000 * i);
      })(i);
    }
    setTimeout(function () {
      console.log(i);
    }, 1000 * i);
  • es6的方法
    let tasks = [];
    function sleep(i) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log(i);
          resolve();
        }, 1000 * i);
      });
    }
    for (let i = 0; i < 5; i++) {
      tasks.push(sleep(i));
    }
    Promise.all(tasks).then(() => {
      setTimeout(() => {
        console.log(i);
      }, 1000);
    });
  • es7的方法:
    function sleep(time) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve();
        }, time);
      });
    }
    (async function () {
      for (var i = 0; i < 5; i++) {
        await sleep(1000);
        console.log(i);
      }
      setTimeout(() => {
        console.log(i);
      }, 1000);
    })();
 
 
 
 
 
 
 
 
北栀女孩儿
原文地址:https://www.cnblogs.com/wxh0929/p/15047790.html