stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包
在这之前先要了解一下
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;循环中的闭包相关推荐
- 调用另一个cpp的变量_再谈条件变量—从入门到出家
再谈条件变量-从入门到出家 C语言--条件变量 条件变量是在线程中以睡眠的方式等待某一条件的发生: 条件变量是利用线程间共享的全局变量进行同步的一种机制: 一个线程等待"条件变量的条件成立& ...
- python 循环语句结果存储_【零基础学Python】循环语句
while循环语句 可以使用while语句一遍又一遍的执行代码块.只要while语句的条件为True,子句的代码就会执行下去.在代码中,一条while语句始终包含以下内容: while关键字 条件(即 ...
- while读取文件 Shell中while循环的陷阱, 变量实效, 无法赋值变量
在写while循环的时候,发现了一个问题,在while循环内部对变量赋值.定义变量.数组定义等等环境,在循环外面失效. 一个简单的测试脚本如下: #!/bin/bash echo "abc ...
- 函数不可以直接调用其他函数内部定义的变量_python的函数
上节课的补充 字典的键(key) 和集合的值都是唯一的,如果插入相同的会进行替换 函数 它可以解决两个问题 1.重复性 2.封装 定义函数语法格式 def + 函数名 + () +: 封装的代码(调用 ...
- 函数不可以直接调用其他函数内部定义的变量_基础知识回顾函数(一)
一.函数的作用 函数就是将一段具有独立功能的代码块整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求.函数在开发过程中,可以更高效的实现代码重用. # 备注:因为在Python里面,函数 ...
- 探究MATLAB循环语句内部的变量
C++中,for循环是一条符合语句,循环控制变量可以定义在这条语句内部,且在这条语句内部,也可以定义其他的变量.循环已结束,这条语句内部定义的变量均会被释放. 我们来看MATLAB是不是这样的,在MA ...
- python循环怎么跳过开始循环,如果循环内部调用的函数执行时间太长,你怎么能跳过python中的循环迭代?...
我想循环一组文件,并对每个文件执行"runthingy()"中指定的操作.但是,由于此操作在某些文件上卡住,导致整个程序停止,因此如果完成此特定文件的时间超过120秒,我希望跳过它 ...
- shell的几个重要命令,主要参数,循环语句以及变量处理
====================================================================== ule-scripts-shell =========== ...
- 【Linux学习笔记④】——Shell程序设计【变量 输入与输出 条件表达式 判断语句 循环语句 Shell函数】
⌛️ 文章目录 一.Shell 概述 二.Shell 脚本的定义与执行 2.1 Shell 脚本的定义 2.2 Shell 脚本的执行 三.Shell 变量 3.1 用户自定义变量 3.2 环境变量 ...
最新文章
- 冰刃——IceSword
- C/S架构程序多种类服务器之间实现单点登录(转)
- 卓京计算机学校,卓京--计算机数据原理课程设计任务书.doc
- SLAM: Inverse Depth Parametrization for Monocular SALM
- Modbus协议栈应用实例之四:ModbusTCP服务器应用
- java把对象转成图片格式转换器安卓版,java 万能图片格式转换
- SpringBoot使用netty
- 数组的属性、foreach遍历、交错数组与矩形数组的区别
- 瑞士联邦议会批准关于加密货币监管的指示
- 【SVM预测】基于蝙蝠算法改进SVM实现数据分类
- kux格式怎么转换成mp3_kux格式如何转换成mp4、mp3?
- 数学建模-灰色系统理论与灰色关联分析
- 如何使iframe透明
- pr导出视频的每一帧
- 离散数学复习二:空集、补集、德摩根定律、异或、广义交和广义并
- 缓解眼睛疲劳:按摩+复调钢琴曲
- numpy ndarry根据条件筛选数据
- 小米电视怎么样?五大标准最有发言权
- C语言--实现汉诺塔【图文讲解,附代码】
- 理解透彻!java微信公众号开发流程