本文来自 @xiaoyuze88 链接:http://xiaoyuze88.github.io/

太久没碰代码了,那天想到关于循环调用setTimeout实现每隔一秒输出递增的数的那个问题,搞了搞,发现很多概念模糊了,在此总结下。

所谓的循环调用setTimeout实现递增输出,就是说用for循环10次,每隔一秒输出一个从0~9的数。

不多说,直接上最终代码再说,细节后面再谈。

for (var i = 0; i < 10; i++) {
//这里用闭包,为每一个i生成一个独立的上下文环境,传递给里面的console.log,而不会受到setTimeout延时而影响
(function (i) {
`setTimeout`(function () {
console.log(i);
}, 1000 * i)
})(i);
}

这里主要的问题在:

  1. 闭包的概念
  2. 也是最终要的,关于setTimeout等函数的工作机制。

首先闭包,这里就不多说了,在这里,闭包的作用就是给闭包内的函数生成一个不受外面环境干扰的上下文环境,由于js的作用域问题。

如果这里不用闭包,写成诸如:

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

会发现,每隔一秒钟,输出一个10。

这是由于这一个for循环的执行,瞬间就完成了,也就是说,瞬间注册了10个延时执行的函数,每一个隔一秒钟执行。

当注册的时间点到来,开始执行setTimeout中的语句,由于定义域的问题,此时console.log(i)的这个i指向的是已经到达10的for循环中的i,这就是为什么要用闭包来给setTimeout设置独立的上下文环境,而避免需要访问i时访问到了外面的变量。

另外,如果细想一下,会发现setTimeout的工作过程多少让人有点迷惑,到底setTimeout等延时类函数在浏览器中是如何运作的?这就牵扯到下一个问题,关于浏览器中是如果运作的问题。

浏览器中,JS引擎是单线程的,假设一个浏览器中有三个常驻线程,既JS引擎线程、渲染线程、事件触发线程,还有处理完即结束的线程如AJAX异步请求。

其中,JS线程与渲染线程是互斥的,这是为了避免JS控制DOM时与页面渲染发生冲突。而对于JS线程,它是由事件驱动的,由于单线程,所有任务依队列排序。如果页面上触发了事件,如onclick=function(){}、或者由setTimeout添加了一个函数、ajax请求返回的事件等,所有新添加的任务位于队尾等待处理。

由于是单线程,如果线程被阻塞,如while(true){}死循环,则一切新添加的任务都将被阻塞。

由上面所述,就可以理解为什么setTimeout或setInterval设置的延时事件并不是真是函数处理的延时时间,既setTimout(code,1000)并不是一定会在1秒后处理,这段代码发生的仅仅是在1秒后,将待处理函数排与js任务队列末尾。

前端读者 | 由setTimeout引发的JS引擎运行机制的研究的更多相关文章

  1. 试着讲清楚:js代码运行机制

    一. js运行机制 js执行引擎 经常看文章的说到js是带线程的,其实这个说法非常的模糊,准确的是js执行引擎是单线程的,js执行引擎就是js代码的执行器,有了这个概念就可以下来说说js是如何运行的了 ...

  2. JS的运行机制

    代码块: JS中的代码块是指由<script>标签分割的代码段.JS是按照代码块来进行编译和执行的,代码块间相互独立(即就算代码块1出错,但不影响代码块2的加载和执行),但变量和方法共享. ...

  3. 关于js内部运行机制的一本好书

    读<单页Web应用一书>,第二章讲了js内部运行机制,感觉棒极了.之前读<你不知道的js>,看的云里雾里,似懂非懂.没想到单页Web一书将此内容讲的如此通俗易懂,好多困惑已久的 ...

  4. 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)

    首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...

  5. JS 引擎执行机制

    JS JS 是单线程语音 JS 的 Event Loop 是 JS 的执行机制.类似于 Android Handler 消息分发机制 JS 单线程 技术的出现都跟现实世界里的应用场景密切相关 JS 单 ...

  6. 从Event Loop谈JS的运行机制

    这里主要是结合Event Loop来谈JS代码是如何运行的. 事件循环对于我们平时开发可以说是特别重要,可以让我们写出更好的代码. 到这里相信我们已经知道了JS引擎是单线程,而且这里会用到前面说的的几 ...

  7. 《JavaScript总结》js的运行机制

    首先大家都知道javascript是单线程语言. 什么是单线程呢?比如我们去车站买票,只有一个售票窗口,大家排队买票,需要前面的人买完票,后面的人才能买票. 那为什么javascript不能是多线程呢 ...

  8. cocos2d-x C++ 原始工程引擎运行机制解析

    新建一个工程,相信感兴趣的同学都想知道cocos引擎都是如何运行的 想知道是如何运行的,看懂四个文件即可 话不多说,上代码: 1.首先解释 AppDelegate.h #ifndef _APP_DEL ...

  9. JS中==运行机制

    1. 判断两边是否有NaN,如果有则一律返回false 2.判断两边是否含有布尔值,如果有的话则将true转化为1,false转化为0. 3.遇到null或者undefined,则不会进行类型转换,它 ...

随机推荐

  1. HDU1083 :Courses(二分图匹配)

    Cources Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

  2. JS 中类型鉴别

    JS中的基本类型有:数字(Number(NaN,Infinity)),字符串(String),Undefined,Null,Boolean 引用类型有:数组(Array),对象(Object),函数( ...

  3. php中相关函数

    1.php标准风格 <?php //这是标准风格 echo '推荐标准风格'; ?> 2.php中文乱码 .html:<meta http-equiv="Content-T ...

  4. 珠排序Bead Sort

    珠排序非常另类[地精也很另类],看完你就知道了,先介绍思路,再分解过程 这是它的英文论文 http://www.cs.auckland.ac.nz/~jaru003/research/publicat ...

  5. 原生js实现单屏滚动

    类似于fullpage的单屏滚动,使用原生JS实现,不依赖任何js库: css: html,body {height:100%;} body {margin:0px;} div {height:100 ...

  6. Asp.Net Web Forms/MVC/Console App中使用Autofac

    本来简单介绍了Autofac在Asp.Net Web Forms中的应用,后来又添加了mvc.控制台应用程序中使用Autofac,详情请看源码. ASP.NET Web Forms使用Autofac, ...

  7. Solaris 选择使用不同网口的操作

    机器上集成两个物理网口,由于先前使用的网口传输速率特别慢且容易丢包,故换成另一个网口,操作如下: 1.查看物理设备信息-- 显示可用的数据链路 root@238-spa:~# dladm show-p ...

  8. AndroidStudio创建jinLibs文件夹

    在文件中的buildTypes节点下添加 sourceSets.main {          jniLibs.srcDir 'libs'      } 如图

  9. jeecg3.7中弹出窗操作标签dgOpenOpt的用法

    1.基本参数 参数名                    描述 url                           弹出页面地址 title                         ...

  10. linux编程之多线程编程

    我们知道,进程在各自独立的地址空间中运行,进程之间共享数据需要用mmap或者进程间通信机制,有些情况需要在一个进程中同时执行多个控制流程,这时候线程就派上了用场,比如实现一个图形界面的下载软件,一方面 ...