在这之前先要了解一下

for循环中let 和var的区别

var 是函数级作用域或者全局作用域,let是块级作用域 看一个例子

    function foo() {

      for (var index = 0; index < array.length; index++) {

        //..循环中的逻辑代码

      }

      console.log(index);//=>5

    }

    foo()

   console.log(index)//Uncaught ReferenceError: index is not defined

foo函数下的index输出5,全局下的index不存在

现在我们把var 换为let

    function foo() {

      for (let index = 0; index < array.length; index++) {

        //..循环中的逻辑代码

      }

      console.log(index)//Uncaught ReferenceError: index is not defined

    }

    foo()

报错了,index不在foo函数作用域下,当然肯定也不会再全局下

因为var和let的这个区别(当然var和let的区别不止于此)所以导致了下面的这个问题

关于var

    const array = [1, 2, 3, 4, 5]

    function foo() {

      for (var index = 0; index < array.length; index++) {

        setTimeout(() => {

          console.log(index);

        }, 1000);

      }

    }

    foo()

看下输出

关于let的

    const array = [1, 2, 3, 4, 5]

    function foo() {

      for (let index = 0; index < array.length; index++) {

        setTimeout(() => {

          console.log(index);

        }, 1000);

      }

    }

    foo()

看下输出

因为var和let 在作用域上的差别,所以到这了上面的问题

使用var 定义变量的时候,作用域是在foo函数下,在for循环外部,在整个循环中是全局的,每一次的循环实际上是为index赋值,循环一次赋值一次,5次循环完成,index最后的结果赋值就为5;就是被最终赋值的index,就是5;

let的作用局的块级作用局,index的作用域在for循环内部,即每次循环的index的作用域就是本次循环,下一次循环重新定义变量index;所以index每次循环的输出都不同

这里还有另外一个问题,setTimeout,这是一个异步,这就是我们今天要讨论的

循环中的异步

setTimeout(func,time)函数运行机制

setTimeout(func,time)是在time(毫秒单位)时间后执行func函数。浏览器引擎按顺序执行程序,遇到setTimeout会将func函数放到执行队列中,等到主程序执行完毕之后,才开始从执行队列(队列中可能有多个待执行的func函数)中按照time延时时间的先后顺序取出来func并执行。即使time=0,也会等主程序运行完之后,才会执行。

一个需求,一个数组array[1,2,3,4,5],循环打印,间隔1秒

上面的let是循环打印了12345,但是不是间隔1s打印的,是在foo函数执行1s后,同时打印的

方式一, 放弃for循环,使用setInterval

    function foo(){

      let index = 0;

      const array = [1, 2, 3, 4, 5]

      const t = setInterval(()=>{

        if (index < array.length) {

          console.log(array[index]);

        }

        index++;

      }, 1000);

      if (index >= array.length) {

        clearInterval(t);

      }

    }

    foo()

我们上面说到,当for循环遇到了var,变量index的作用域在foo函数下,循环一次赋值一次,5次循环完成,index最后的结果赋值就为5;就是被最终赋值的index,就是5;

方式二,引入全局变量

代码执行顺序是,先同步执行for循环,再执行异步队列,在for循环执行完毕后,异步队列开始执行之前,index经过for循环的处理,变成了5。

所以我们引入一个全局变量j,使j在for循环执行完毕后,异步队列开始执行之前,依然是0,在异步执行时进行累加

    var j = 0;

    for (var index = 0; index < array.length; index++) {

      setTimeout(() => {

        console.log(j);

        j++;

      }, 1000 * index)

    }

方式三, for循环配合setTimeout(常规思路,不赘述,面试必备技能)

    const array = [1, 2, 3, 4, 5]

    function foo() {

      for (let index = 0; index < array.length; index++) {

        setTimeout(() => {

          console.log(index);

        }, 1000*index);

      }

    }

    foo()

方式四,通过闭包实现

开始讨论方式四之前我推荐先阅读一遍我之前写过一篇文章

谈一谈javascript作用域

我们对上面的问题再次分析,for循环同步执行,在for循环内部遇到了setTimeout,setTimeout是异步执行的,所以加入了异步队列,当同步的for循环执行完毕后,再去执行异步队列,setTimeout中有唯一的一个参数数index

方式三可行,是因为let是块级作用域,每次for执行都会创建新的变量index,for循环执行完毕后,异步执行之前,创建了5个独立的作用域,5个index变量,分别是0,1,2,3,4,相互独立,互不影响,输出了预期的结果

如果说每次循环都会生成一个独立的作用域用来保存index,问题就会得到解决,所以,我们通过闭包来实现

    const array = [1, 2, 3, 4, 5]

    function foo() {

      for (var index = 0; index < array.length; index++) {

        function fun(j) {

          setTimeout(function () {

            console.log(j);

          }, 1000 * j);

        }

        fun(index)

      }

    }

    foo()

setTimeout中的匿名回调函数中引用了函数fun中的局部变量j,所以当fun执行完毕后,变量j不会被释放,这就形成了闭包

当然我们可以对此进行一下优化

    const array = [1, 2, 3, 4, 5]

    function foo() {

      for (var index = 0; index < array.length; index++) {

        (function(j) {

          setTimeout(function () {

            console.log(j);

          }, 1000 * j);

        })(index)

      }

    }

    foo()

将foo函数改为匿名的立即执行函数,结果是相同的

总结

for循环本身是同步执行的,当在for循环中遇到了异步逻辑,异步就会进入异步队列,当for循环执行结束后,才会执行异步队列 当异步函数依赖于for循环中的索引时(一定是存在依赖关系的,不然不会再循环中调动异步函数)要考虑作用域的问题,

在ES6中使用let是最佳的选择

当使用var时,可以考虑再引入一个索引来替代for循环中的索引,新的索引逻辑要在异步中处理

也可以使用闭包,模拟实现let 在实际开发过程中,循环调用异步函数,比demo要复杂,可能还会出现if和else判断等逻辑,具体的我们下次再续

stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包相关推荐

  1. 调用另一个cpp的变量_再谈条件变量—从入门到出家

    再谈条件变量-从入门到出家 C语言--条件变量 条件变量是在线程中以睡眠的方式等待某一条件的发生: 条件变量是利用线程间共享的全局变量进行同步的一种机制: 一个线程等待"条件变量的条件成立& ...

  2. python 循环语句结果存储_【零基础学Python】循环语句

    while循环语句 可以使用while语句一遍又一遍的执行代码块.只要while语句的条件为True,子句的代码就会执行下去.在代码中,一条while语句始终包含以下内容: while关键字 条件(即 ...

  3. while读取文件 Shell中while循环的陷阱, 变量实效, 无法赋值变量

    在写while循环的时候,发现了一个问题,在while循环内部对变量赋值.定义变量.数组定义等等环境,在循环外面失效. 一个简单的测试脚本如下: #!/bin/bash echo "abc ...

  4. 函数不可以直接调用其他函数内部定义的变量_python的函数

    上节课的补充 字典的键(key) 和集合的值都是唯一的,如果插入相同的会进行替换 函数 它可以解决两个问题 1.重复性 2.封装 定义函数语法格式 def + 函数名 + () +: 封装的代码(调用 ...

  5. 函数不可以直接调用其他函数内部定义的变量_基础知识回顾函数(一)

    一.函数的作用 函数就是将一段具有独立功能的代码块整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求.函数在开发过程中,可以更高效的实现代码重用. # 备注:因为在Python里面,函数 ...

  6. 探究MATLAB循环语句内部的变量

    C++中,for循环是一条符合语句,循环控制变量可以定义在这条语句内部,且在这条语句内部,也可以定义其他的变量.循环已结束,这条语句内部定义的变量均会被释放. 我们来看MATLAB是不是这样的,在MA ...

  7. python循环怎么跳过开始循环,如果循环内部调用的函数执行时间太长,你怎么能跳过python中的循环迭代?...

    我想循环一组文件,并对每个文件执行"runthingy()"中指定的操作.但是,由于此操作在某些文件上卡住,导致整个程序停止,因此如果完成此特定文件的时间超过120秒,我希望跳过它 ...

  8. shell的几个重要命令,主要参数,循环语句以及变量处理

    ====================================================================== ule-scripts-shell =========== ...

  9. 【Linux学习笔记④】——Shell程序设计【变量 输入与输出 条件表达式 判断语句 循环语句 Shell函数】

    ⌛️ 文章目录 一.Shell 概述 二.Shell 脚本的定义与执行 2.1 Shell 脚本的定义 2.2 Shell 脚本的执行 三.Shell 变量 3.1 用户自定义变量 3.2 环境变量 ...

最新文章

  1. 冰刃——IceSword
  2. C/S架构程序多种类服务器之间实现单点登录(转)
  3. 卓京计算机学校,卓京--计算机数据原理课程设计任务书.doc
  4. SLAM: Inverse Depth Parametrization for Monocular SALM
  5. Modbus协议栈应用实例之四:ModbusTCP服务器应用
  6. java把对象转成图片格式转换器安卓版,java 万能图片格式转换
  7. SpringBoot使用netty
  8. 数组的属性、foreach遍历、交错数组与矩形数组的区别
  9. 瑞士联邦议会批准关于加密货币监管的指示
  10. 【SVM预测】基于蝙蝠算法改进SVM实现数据分类
  11. kux格式怎么转换成mp3_kux格式如何转换成mp4、mp3?
  12. 数学建模-灰色系统理论与灰色关联分析
  13. 如何使iframe透明
  14. pr导出视频的每一帧
  15. 离散数学复习二:空集、补集、德摩根定律、异或、广义交和广义并
  16. 缓解眼睛疲劳:按摩+复调钢琴曲
  17. numpy ndarry根据条件筛选数据
  18. 小米电视怎么样?五大标准最有发言权
  19. C语言--实现汉诺塔【图文讲解,附代码】
  20. 理解透彻!java微信公众号开发流程

热门文章

  1. SQL char字段类型排序
  2. iOS 根据日期判断星座源代码
  3. QT5完成一个数据实时显示控制的Demo
  4. C# 对象与JSON字符串互相转换的三种方式
  5. 简单的MFC画正弦曲线
  6. C++静态成员和非静态成员的区别 及修饰
  7. swift5优秀打印函数自定义
  8. IOS9+基础之警报框弹出和操作表弹出
  9. IOS开发基础之网易新闻环境搭建异步请求json,AFN网络封装第1天
  10. mysql-nt.exe w3wp.exe cpu 100%_认识w3wp.exe进程,从根本上解决占用资源较大问题