for循环+setTimeout的延迟操作
例子:
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, 100)
}
上述代码,输出结果显而易见是5个5,且并没有任何的延迟效果。那么为什么呢?
首先这样的结果需要从JS的执行机制说起。JS是单线程环境,也就是说代码的执行是从上到下,依次执行。这样的执行称为同步执行。因为种种不要浪费和节约的原因。JS中引进了异步的机制。在这段代码中,哪个是同步哪个是异步呢?for循环是同步代码,而setTimeout中的是异步代码。那么JS碰到这个有同步和异步的情况下会先从上到下执行同步代码,碰到异步的代码会将其插入到任务队列当中等待。而setTimeout是延时,也就是说碰到setTimeout这个异步的代码块会根据它里面的第二个参数:延时时间来将代码插入到任务队列当中,比如上面这段代码中,第二个参数延时时间是100,也就是说执行到它的时候会在100ms之后将它插入到任务队列当中。同步代码都执行完成之后,那么JS引擎就空闲了,这个时候就轮到任务队列中的异步代码依次加载了。
这是上面这段代码的答案的一半。另一半就来自于作用域,作用域是变量等资源的作用范围。在这段代码中准确的说是作用域链的问题,当同步代码执行完毕开始执行异步的setTimeout代码时,setTimeout中需要一个变量i,而执行的时候在当前的作用域中开始找,找不到变量i的定义,这个时候就把创建这个函数的作用域作为当前作用域,再次寻找,创建这个函数的作用域就是全局作用域,也就是找到了for循环中i,找到了之后就结束寻找变量i的行程。由于这个时候的i是全局的,而且人家已经变为了最终形态:5,setTimeout找到的就是这个i=5;所以就输出了5,下面的4次setTimeout 的执行都是类似,所以结果都是5;
所以我对这个答案的理解归结起来就是 异步加载+作用域链。
正确写法:
for (var i = 0; i < 5; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
}, 100 * i);
})(i);
}
将延迟操作闭包,立即执行。
for循环+setTimeout的延迟操作的更多相关文章
- for循环 + setTimeout 结合的烂大街的面试题
零.背景 最近在翻看以前的老书<node.js开发指南>,恰好碰到for循环 + setTimeout的经典例子,于是重新梳理了思路并记录下. 一.写在前面,setTimeout和setI ...
- [从源码学设计]蚂蚁金服SOFARegistry之延迟操作
[从源码学设计]蚂蚁金服SOFARegistry之延迟操作 0x00 摘要 SOFARegistry 是蚂蚁金服开源的一个生产级.高时效.高可用的服务注册中心. 本系列文章重点在于分析设计和架构,即利 ...
- js获取时间,循环执行任务,延迟执行任务
一.获取时间 核心方法创建一个时间对象:new Date() 时间对象相关操作 时间对象.函数名 函数名 功能 getYear() 获取四位数的年份 getMonth() 获取2位数的月数, 这个是从 ...
- 数据结构--线段树--lazy延迟操作
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 53749 ...
- 关于for循环与setTimeout的延迟
在for循环中使用setTimeout时,想使其每个setTimeout在上一个setTimeout的基础上进行延时,使用传入数组方式设置时间时,发现实际是按照每次设置的setTimeout的延时执行 ...
- 深浅拷贝, for循环小知识点 str操作 list的删除问题,类型转换
深浅拷⻉ : lst1 = ["⾦⽑狮王", "紫衫⻰王", "⽩眉鹰王", "⻘翼蝠王"] lst2 = lst1 ...
- python2学习------基础语法1 (变量、分支语句、循环语句、字符串操作)
1.变量类型 Numbers(数字):int,float,long String(字符串) List(列表) tuple(元组) dict(字典) bool(布尔):True,False # 删除变量 ...
- JavaScript循环和数组常用操作
while循环 语法: do while循环 语法:do{循环体}while(条件表达式); 特点:do while循环不管条件是否成立,无论如何循环体都会执行一次. 使用场合:用户输入密码,如果密码 ...
- 循环时的dom操作
<body> <div id="resText"></div> <div id="reshtml"></d ...
随机推荐
- Python的基础知识01 _个人笔记
1.快捷键:Alt+n 回到上一条语句>把上一条语句复制 Alt+p 去到下一条语句 2.Python 中不用“:”来表示一个语句 3.print("I Love you" ...
- Codeforces Round #471 (Div. 2)A. Feed the cat
After waking up at hh:mm, Andrew realised that he had forgotten to feed his only cat for yet another ...
- 微信小程序 Image 图片实现宽度100%,高度自适应
做法如下: 样式设置宽度100%, .img{ width:100%;} 添加属性 mode="widthFix", <image class="img" ...
- ArcGIS中标格乱码??
安装好ArcGIS之后导入地图层之后,显示 label 时中文乱码,但是导出数据显示正常 这是 ArcGIS 安装环境编码的问题,只需要修改一下配置文件即可 打开 cmd 命令窗口 reg add H ...
- 【codeforces 803D】Magazine Ad
[题目链接]:http://codeforces.com/contest/803/problem/D [题意] 给你一个字符串; 其中的空格和连字符表示可以折叠的部分 (就是说能在那个位置把字符串分成 ...
- 如何利用eclipse实现批量修改文件的编码方式
在eclipse+Eclipse环境下,打开一个jsp文件,经常发现汉字无法显示,右键点击查看这个文件属性,发现文件的字符编码属性为ISO-8859-1. 目前的解决方法有:1. 手工把 ...
- Servlet过滤器和监听器知识总结
Servlet过滤器是 Servlet 程序的一种特殊用法,主要用来完成一些通用的操作,如编码的过滤.判断用户的登录状态.过滤器使得Servlet开发者能够在客户端请求到达 Servlet资源之前被截 ...
- iOS开发一行代码系列:一行搞定输入框
近期总结了下开发过程中经常使用的功能,发现有时候我在做反复性的劳动.于是决定把经常使用的功能抽出来,方便下次使用. 我的想法是:用最少的代码来解决这个问题.于是写了一些经常使用的工具类,名字就叫一行代 ...
- POJ3249 Test for Job(拓扑排序+dp)
Test for Job Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10137 Accepted: 2348 Des ...
- windows下PTAM的编译
前些日子在研究PTAM,以下首先说说PTAM的编译过程,我在XP几WIN7搭配vs2010中均已測试过,都能够执行. 首先下载编译PTAM所必须的库文件.下载地址我会给出 PTAM(PTAM.zip) ...