易错javascript编程题汇总(2)
来源:互联网 发布:node.js urlencoder 编辑:程序博客网 时间:2024/06/07 11:50
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log('i: ',i); }, 1000);}console.log(i);//输出i:5i:5i:5i:5i:5
为什么会这样而不是i:1 i:2 I:3 i:4 i:5 呢?
因为 同步 => 异步 => 回调
1、for循环和循环体外部的console是同步的,所以先执行for循环,再执行外部的console.log。(同步优先)
2、for循环里面有一个setTimeout回调,他是垫底的存在,只能最后执行。(回调垫底)
那么,为什么我们最先输出的是5呢?
非常好理解,for循环先执行,但是不会给setTimeout传参(回调垫底),等for循环执行完,就会给setTimeout传参,而外部的console打印出5是因为for循环执行完成了。
这里涉及到JavaScript执行栈和消息队列的概念,概念的详细解释可以看阮老师的 JavaScript 运行机制详解:再谈Event Loop – 阮一峰的网络日志,或者看 并发模型与Event Loop
JavaScript单线程如何处理回调呢?JavaScript同步的代码是在堆栈中顺序执行的,而setTimeout回调会先放到消息队列,for循环每执行一次,就会放一个setTimeout到消息队列排队等候,当同步的代码执行完了,再去调用消息队列的回调方法。
在这个经典例子中,也就是说,先执行for循环,按顺序放了5个setTimeout回调到消息队列,然后for循环结束,下面还有一个同步的console,执行完console之后,堆栈中已经没有同步的代码了,就去消息队列找,发现找到了5个setTimeout,注意setTimeout是有顺序的。
那么,setTimeout既然在最后才执行,那么他输出的i又是什么呢?答案就是5。
因为i是用var定义的,所以var是全局变量(这里没有函数,如果有就是函数内部的变量),这个时候的i是5,从外部的console输出结果就可以知道。那么当执行setTimeout的时候,由于全局变量的i已经是5了,所以传入setTimeout中的每个参数都是5。
更多例题
for (var i = 0; i < 5; ++i) { setTimeout(function() { console.log('2: ',i); }, 1000); console.log('1: ', i); //新加一行代码}console.log(i);//输出1: 01: 11: 21: 31: 452: 52: 52: 52: 52: 5
作者:hyy1115
segmentfault.com/a/1190000008922457
更多详情见:微信公众号 前端大全
- 易错javascript编程题汇总(2)
- 易错JavaScript编程题汇总(1)
- 易错JavaScript编程题汇总(3)
- 编程题汇总2
- 《Javascript DOM编程艺术》第2版 知识点汇总
- JavaScript关键知识点汇总(2):Array
- Java面试编程题汇总(1)
- LintCode编程题汇总(更新中)
- 编程基础理论题汇总
- 编程题汇总
- 编程题汇总1
- 编程题汇总3
- 编程题汇总4
- 编程题汇总5
- java编程经验汇总(2)
- 《JavaScript语言精髓与编程实践》(第二版)相关资源汇总
- javascript 汇总
- 【牛客网】算法编程题汇总
- pyshon实现一天前,一月前,一年前的日期计算
- Linux下编译安装源代码的三个步骤
- hexo文章中插入图片
- web.xml is missing and <failOnMissingWebXml> is set to true
- C++ 函数参数、返回值效率测试
- 易错javascript编程题汇总(2)
- 设计模式6大设计原则解读——依赖倒置原则
- iOS类似墙纸透视效果UIInterpolatingMotionEffect
- 设计原则
- Visual Studio 项目中添加include, lib, dll库文件(*.h,*.lib,*.dll)
- 设计模式之单例模式(Singleton)
- kali linux Python 黑客编程1 开发环境初始化
- 搜索 L题
- 写给自己