题目:

for(var i=0;i<=3;i++){ setTimeout(function() {  console.log(i)  }, 10);}

理想答案是输出:0,1,2,3

实际答案是输出:4,4,4,4

这道题看似简单,其实涉及了js中关于异步、作用域、闭包的问题

首先settimeout是异步执行函数,执行settimeout函数时,会在主线任务外增加一个新的任务队列,10ms后往新的任务队列里面添加settimeout内部的任务,只有主线上的任务全部执行完,才会执行新的任务队列里的任务,当主线执行完成后,i的值是4,所以此时再去执行任务队列里的任务时,i全部是4了。

  于是上面题目就不难理解了:

每一次for循环的时候,settimeout都执行一次,但是里面的函数没有被执行,而是被放到了任务队列里面,等待执行,for循环了4次,就放了4个任务,当主线程执行完成后,才进入任务队列里面执行。
(注意:for循环从开始到结束的过程,需要维持几微秒或几毫秒。)
解决方法:
 第1种 把var 变成let 改变作用域
for(let i=0;i<=3;i++){ setTimeout(function() {  console.log(i)  }, 10);}
输出的是:0,1,2,3
因为for循环头部的let不仅将i绑定到for循环快中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的function()属于一个新的域,通过 var 定义的变量是无法传入到这个函数执行域中的,通过使用 let 来声明块变量,这时候变量就能作用于这个块,所以 function就能使用 i 这个变量了;这个匿名函数的参数作用域 和 for参数的作用域 不一样,是利用了这一点来完成的。这个匿名函数的作用域有点类似类的属性,是可以被内层方法使用的。

第二种  给settimeout的内部函数加一个闭包,让其立即执行

for(var i=0;i<=3;i++){
  setTimeout(
    (function() {
      console.log(i);
    })()//此函数会立即执行
  , 10);
}

转载于:https://www.cnblogs.com/webwangjie/p/8617859.html

异步、作用域、闭包--setTimeout在for循环中的思考相关推荐

  1. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  2. 探究点击事件在JavaScript事件循环中的表现

    JavaScript的事件循环event loop很多文章都写的非常详细了.这里也不多做介绍. 在很多文章中都有介绍鼠标事件Mouse Event是属于macrotask.本文探究一下Mouse Ev ...

  3. stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包

    在这之前先要了解一下 for循环中let 和var的区别 var 是函数级作用域或者全局作用域,let是块级作用域 看一个例子     function foo() {       for (var  ...

  4. 你不知道的三种在for循环中使用setTimeout的方法

    在 for 循环中使用 setTimeout 中可能会出现结果输出不符合预期: for (var i = 0; i < 5; i++) {setTimeout(() => {console ...

  5. for 循环中使用 setTimeout 的问题

    问题引入 下面代码的输出结果不是间隔3秒依次输出 1, 2, 3, 4, 5.而是隔了3秒连续输出6.这是为什么呢? for (var i = 1; i <= 5; i++){     setT ...

  6. 在for循环中运行setTimeout

    先看一段代码 for (var i=0; i<10; i++) { setTimeout(console.log(i), i*1000 );} 答案:0.1.2.3.4.5.6.7.8.9 再比 ...

  7. ES6中let的用法及一个小案例,在for循环中运行setTimeout的四种情况:

    1.ES6中let和var的主要区别: (1)let声明的变量只在当前块级作用域内有效. if(true){var a=1;let b=2; } console.log(a); console.log ...

  8. JavaScript中的作用域,闭包和上下文

    深入理解JavaScript中的作用域和上下文 很多语言当中都会有作用域的概念,它会给我们带来便利,偶尔也会有烦恼,只有清楚地理解和掌握了它,才能更好地为我所用,今天就带来这么一篇文章供大家参考. 介 ...

  9. js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)...

    javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...

最新文章

  1. java 对象 php对象_java对象是什么?
  2. [Python人工智能] 五.Tensorboard可视化基本用法及绘制整个神经网络
  3. Delphi第三方组件安装DCU.PAS.DPK.BPL.ActiveX控件
  4. 《赢在测试2》-- 推荐的阅读书籍
  5. JAVA解压tar,可以使用javatar
  6. linux上apk免杀,kali 免杀工具shellter安装以及使用(示例代码)
  7. Win7系统上的appdata是什么文件夹可以删除roaming
  8. c语言编程照抄能学好吗,电子信息类专业学生必看:一位老电子工程师十年感悟...
  9. Spring之Introductions(简介)应用
  10. MPI_Bcast与MPI_Comm_split配合,实现行广播或列广播
  11. 微信运营营销推广方案
  12. VMware ESXI 下虚拟机时间问题
  13. 大学数学建模大赛是用计算机,全国大学生数学建模大赛
  14. Linux下命令行中的复制和粘贴
  15. 4 轮拿下字节 Offer,面试题复盘
  16. linux给音乐添加封面,linux系统获取MP3的专辑封面图片
  17. 密歇根安娜堡大学的计算机科学教授,密歇根大学安娜堡分校计算机科学与工程研究生offer及申请要求...
  18. 广州种植牙费用需要大约是多少-南方卫视
  19. 随手记录第六话 -- 在Mac上搭建整个开发环境记录(Java、Python、Vue、Docker、idea)
  20. 基于Java+Springboot+Vue+elememt美食论坛平台设计实现

热门文章

  1. 华为云王红新_Veritas与华为云签署合作谅解备忘录推进云数据安全进阶
  2. CheckCode.js 前端验证码插件
  3. 开源炫酷css轮播图 可直接引入html文件使用 含注释 jQuery插件
  4. 在WinSCP中使用sudo进行sftp,不用输入密码,获得root权限
  5. php正则匹配td,正则表达式-查找td标签之间的所有内容 - php
  6. android 图片放大缩小_几款堪称神器的图片无损放大缩小工具!
  7. java面向对象思维导图_2020年Java进阶架构师的必备思维导图,让你少走弯路!
  8. 如何在简历中添加自己的CSDN博客链接
  9. 计算机上的应用商城,Windows 应用商店帐户将应用安装在多达五台电脑上
  10. Docker(五):Docker Volume