这两天在捣鼓作用域的问题,有的时候知识这个东西真的有点像是牵一发而动全身的感觉。在理解作用域的时候,又看到了一道经典的面试题和例子题。

那就是在for循环中嵌套setTimeout延时,想想之前面试的时候面试官问到我这个问题,然而我当时对这玩意儿根本没有深究,没有去理解;非常草率的回答了,面试官好心的给我

说这个涉及到setTimeout回调函数异步特性,啪啦啪啦,说的好几句都感觉晕乎了~也感觉JS这个东西真的需要深入的东西还很多,路也还很长。

直接进入主题了,先贴一段简单的代码:

结果是10次10。不得不说看到答案的第一眼真的魔怔啊,完全不理解为什么是10次10;只有你多去了解JS的执行机制之后,或许心中就有答案了。所以以下是我个人在看了众多的

网上的各位高手的见解之后,总结以下得到的一个见解。如有歧义,欢迎各位的指正。

首先这样的结果需要从JS的执行机制说起。JS是单线程环境,也就是说代码的执行是从上到下,依次执行。这样的执行称为同步执行。因为种种不要浪费和节约的原因。JS中引进了异步的机制。在这段代码中,哪个是同步哪个是异步呢?for循环是同步代码,而setTimeout中的是异步代码。那么JS碰到这个有同步和异步的情况下会先从上到下执行同步代码,碰到异步的代码会将其插入到任务队列当中等待。而setTimeout是延时,也就是说碰到setTimeout这个异步的代码块会根据它里面的第二个参数:延时时间来将代码插入到任务队列当中,比如上面这段代码中,第二个参数延时时间是0,也就是说执行到它的时候会在0ms之后将它插入到任务队列当中。同步代码都执行完成之后,那么JS引擎就空闲了,这个时候就轮到任务队列中的异步代码依次加载了。

这是上面这段代码的答案的一半。另一半就来自于作用域,作用域是变量等资源的作用范围。在这段代码中准确的说是作用域链的问题,当同步代码执行完毕开始执行异步的setTimeout代码时,setTimeout中需要一个变量 ---i---,而执行的时候在当前的作用域中开始找,找不到变量i的定义,这个时候就把创建这个函数的作用域作为当前作用域,再次寻找,创建这个函数的作用域就是全局作用域,也就是找到了for循环中i,找到了之后就结束寻找变量i的行程。由于这个时候的i是全局的,而且人家已经变为了最终形态:10,setTimeout找到的就是这个i=10;所以就输出了10,下面的9次setTimeout 的执行都是类似,所以结果都是10;

所以我对这个答案的理解归结起来就是  异步加载+作用域链。可见要理解一段看似简单的代码,要去学习的东西还真不少。

问题出来了,相应的就有解决方案;对于这类问题比较常见的解决方法就是 立即执行函数。它逼迫js每次循环进来的时候都会立即去执行代码,从而保证了每一次得到了i的副本都是不一样的。贴代码:

如上图,得到了想要的答案

for循环中嵌套setTimeout,执行顺序和结果该如何理解?的更多相关文章

  1. JS中For循环中嵌套setTimeout()方法的执行顺序

    在For循环中执行setTimeOut()方法的代码,执行顺序是怎样的呢? 代码如下 function time() { for(var i= 0;i<5;i++){ setTimeout(fu ...

  2. 我敢说你不一定完全理解try 块,catch块,finally 块中return的执行顺序

    大家好,今天我们来讲一个笔试和面试偶尔都会问到的问题,并且在工作中不知道原理,也会造成滥用. 大家可能都知道,try 块用来捕获异常,catch块是处理try块捕获的异常,finally 块是用来关闭 ...

  3. 浅谈循环中setTimeout执行顺序问题

    浅谈循环中setTimeout执行顺序问题 (下面有见解一二) 期望:开始输出一个0,然后每隔一秒依次输出1,2,3,4. for (var i = 0; i < 5; i++) { setTi ...

  4. for循环中嵌套异步请求问题

    for循环中嵌套了异步请求会导致顺序错乱,用递归代替for循环,可以保证正常执行顺序:

  5. jquery ajax中各个事件执行顺序如下

    $(function(){ setTimeout(function(){ $.ajax({ url:'/php/selectStudent.php', }); },0); $(document).aj ...

  6. Unity3D中脚本的执行顺序和编译顺序

    http://www.cnblogs.com/champ/p/execorder.html 在Unity中可以同时创建很多脚本,并且可以分别绑定到不同的游戏对象上,它们各自都在自己的生命周期中运行.与 ...

  7. 【转】Unity3D中脚本的执行顺序和编译顺序(vs工程引用关系)

    http://www.cnblogs.com/champ/p/execorder.html 在Unity中可以同时创建很多脚本,并且可以分别绑定到不同的游戏对象上,它们各自都在自己的生命周期中运行.与 ...

  8. jquery中各个事件执行顺序如下:

    jquery中各个事件执行顺序如下: 1.ajaxStart(全局事件) 2.beforeSend 3.ajaxSend(全局事件) 4.success 5.ajaxSuccess(全局事件) 6.e ...

  9. mysql 中sql的执行顺序

    文章转自 https://www.cnblogs.com/annsshadow/p/5037667.html https://www.cnblogs.com/yyjie/p/7788428.html ...

随机推荐

  1. Ubuntu 14.04TLS和CentOS-6(64bit)上安装Nginx

    Ubuntu 14.04上安装Nginx [参考地址]https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on- ...

  2. odoo配置界面设置字段默认值

    转自国外牛人博客:http://ludwiktrammer.github.io/odoo/custom-settings-odoo.html Defining custom settings in O ...

  3. odoo开发笔记:前端显示强制换行

    未调整之前:客户信息显示不全 调整后实现效果: 补充CSS知识: 一.强制换行 word-break: break-all; 只对英文起作用,以字母作为换行依据. word-wrap: break-w ...

  4. 13、最新安卓Xamarin绑定相关填坑之旅

    今天群里面有兄弟伙说第三方库用不起.说实话在我觉得第三方库能成功的几率大于90% 除了极少数恶心的库以外. 绝大部分第三方库都还是可以绑定好的 https://github.com/youzan/Yo ...

  5. ORACLE数据库表解锁record is locked by another user

    出现此问题多由于操作Oracle执行完,没有COMMIT,直接把PL/SQL关闭掉,后来导致那张表被锁住,当编辑时就会出现这个信息,record is locked by another user! ...

  6. python应用

    GUI(图形用户界面) python是可以创建GUI的,使用第三方库一般是Tk.wxWidgets.Qt.GTK. 而python自带的是支持Tk的Tkinter,我们这里就来用Tkinter来实现G ...

  7. pycharm格式化代码 常用快捷键

    ctrl+alt+L 一 常用快捷键 编辑类: Ctrl + D             复制选定的区域或行Ctrl + Y           删除选定的行Ctrl + Alt + L     代码 ...

  8. linux使用find和crontab命令定期清理过期文件

    crontab 命令 crontab 命令是 Linux 中用来设定重复执行命令或脚本的工具.它能够在指定的时间段内,按照需求以某一时间间隔执行命令或脚本. crontab 的基本用法 crontab ...

  9. geo-经纬度计算

    经纬度计算, 本质上是球面三角函数的应用, 将数学公式转换为代码的过程, 站在前人的肩膀上, 自己又补充了一点: package com.iwhere.easy.travel.tool; public ...

  10. wamp配置虚拟路径(路径别名)

    wamp默认的路径是安装目录下的 www 目录, 如果你想运行php代码,就需要将代码放在 www 目录下, 但这样很不方便,能否通过配置的方式,来实现 在别的目录下的 php 代码,也能正常运行和访 ...