例子:

 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的延迟操作的更多相关文章

  1. for循环 + setTimeout 结合的烂大街的面试题

    零.背景 最近在翻看以前的老书<node.js开发指南>,恰好碰到for循环 + setTimeout的经典例子,于是重新梳理了思路并记录下. 一.写在前面,setTimeout和setI ...

  2. [从源码学设计]蚂蚁金服SOFARegistry之延迟操作

    [从源码学设计]蚂蚁金服SOFARegistry之延迟操作 0x00 摘要 SOFARegistry 是蚂蚁金服开源的一个生产级.高时效.高可用的服务注册中心. 本系列文章重点在于分析设计和架构,即利 ...

  3. js获取时间,循环执行任务,延迟执行任务

    一.获取时间 核心方法创建一个时间对象:new Date() 时间对象相关操作 时间对象.函数名 函数名 功能 getYear() 获取四位数的年份 getMonth() 获取2位数的月数, 这个是从 ...

  4. 数据结构--线段树--lazy延迟操作

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 53749   ...

  5. 关于for循环与setTimeout的延迟

    在for循环中使用setTimeout时,想使其每个setTimeout在上一个setTimeout的基础上进行延时,使用传入数组方式设置时间时,发现实际是按照每次设置的setTimeout的延时执行 ...

  6. 深浅拷贝, for循环小知识点 str操作 list的删除问题,类型转换

    深浅拷⻉  : lst1 = ["⾦⽑狮王", "紫衫⻰王", "⽩眉鹰王", "⻘翼蝠王"] lst2 = lst1 ...

  7. python2学习------基础语法1 (变量、分支语句、循环语句、字符串操作)

    1.变量类型 Numbers(数字):int,float,long String(字符串) List(列表) tuple(元组) dict(字典) bool(布尔):True,False # 删除变量 ...

  8. JavaScript循环和数组常用操作

    while循环 语法: do while循环 语法:do{循环体}while(条件表达式); 特点:do while循环不管条件是否成立,无论如何循环体都会执行一次. 使用场合:用户输入密码,如果密码 ...

  9. 循环时的dom操作

    <body> <div id="resText"></div> <div id="reshtml"></d ...

随机推荐

  1. Vue学习之路第十二篇:为页面元素设置内联样式

    1.有了上一篇的基础,接下来理解内联样式的设置会更简单一点,先看正常的css内联样式: <dvi id="app"> <p style="font-si ...

  2. BZOJ 2527 [POI2011]MET-Meteors (整体二分+树状数组)

    题目大意:略 洛谷传送门 整体二分裸题 考虑只有一个国家的情况如何处理 对询问数量二分答案,暴力$O(m)$打差分,求前缀和验证,时间是$O(mlogK)$ 如果有$n$个国家,就是$O(nmlogK ...

  3. [TJOI2008]彩灯

    线性基裸题,求最大线性无关组. 注意:1ll<<i #include <cstdio> int n,m; const int mod=2008; long long b[64] ...

  4. js生产随机数

    var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; var string_le ...

  5. jenkins 自动化部署

    Execute shell Command BUILD_ID=DONTKILLMEif [ ! -d "/usr/jenkins/$JOB_NAME" ]; then mkdir ...

  6. OA项目知识总结2

    BaseAction的抽取 项目中的每个实体类都对应一个action  每个action都都要继承ActionSupport类 已以及实现ModelDriver接口  并且需要注入service 虽然 ...

  7. ContextLoaderListener的说明

    ContextLoaderListener是配置在web.xml里的,具体如下: <!-- ContextLoaderListener是个监听器,用来监听容器启动事件,监听到容器启动事件后 其c ...

  8. 跳出$.each()循环

    return false:将停止循环 ,跳出eachreturn true:跳至下一个循环(就像在普通的循环中使用'continue').

  9. G - Arctic Network

    G - Arctic Network   #include<cmath> #include<cstdio> #include<cstring> #include&l ...

  10. 在WPF的MVVM框架中获取下拉选择列表中的选中项

    文章概述: 本演示介绍怎样在WPF的MVVM框架中.通过数据绑定的方式获取下拉列表中的选中项.程序执行后的效果例如以下图所看到的: 相关下载(代码.屏幕录像):http://pan.baidu.com ...