前端读者 | 由setTimeout引发的JS引擎运行机制的研究
本文来自 @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);
}
这里主要的问题在:
- 闭包的概念
- 也是最终要的,关于
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引擎运行机制的研究的更多相关文章
- 试着讲清楚:js代码运行机制
一. js运行机制 js执行引擎 经常看文章的说到js是带线程的,其实这个说法非常的模糊,准确的是js执行引擎是单线程的,js执行引擎就是js代码的执行器,有了这个概念就可以下来说说js是如何运行的了 ...
- JS的运行机制
代码块: JS中的代码块是指由<script>标签分割的代码段.JS是按照代码块来进行编译和执行的,代码块间相互独立(即就算代码块1出错,但不影响代码块2的加载和执行),但变量和方法共享. ...
- 关于js内部运行机制的一本好书
读<单页Web应用一书>,第二章讲了js内部运行机制,感觉棒极了.之前读<你不知道的js>,看的云里雾里,似懂非懂.没想到单页Web一书将此内容讲的如此通俗易懂,好多困惑已久的 ...
- 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)
首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...
- JS 引擎执行机制
JS JS 是单线程语音 JS 的 Event Loop 是 JS 的执行机制.类似于 Android Handler 消息分发机制 JS 单线程 技术的出现都跟现实世界里的应用场景密切相关 JS 单 ...
- 从Event Loop谈JS的运行机制
这里主要是结合Event Loop来谈JS代码是如何运行的. 事件循环对于我们平时开发可以说是特别重要,可以让我们写出更好的代码. 到这里相信我们已经知道了JS引擎是单线程,而且这里会用到前面说的的几 ...
- 《JavaScript总结》js的运行机制
首先大家都知道javascript是单线程语言. 什么是单线程呢?比如我们去车站买票,只有一个售票窗口,大家排队买票,需要前面的人买完票,后面的人才能买票. 那为什么javascript不能是多线程呢 ...
- cocos2d-x C++ 原始工程引擎运行机制解析
新建一个工程,相信感兴趣的同学都想知道cocos引擎都是如何运行的 想知道是如何运行的,看懂四个文件即可 话不多说,上代码: 1.首先解释 AppDelegate.h #ifndef _APP_DEL ...
- JS中==运行机制
1. 判断两边是否有NaN,如果有则一律返回false 2.判断两边是否含有布尔值,如果有的话则将true转化为1,false转化为0. 3.遇到null或者undefined,则不会进行类型转换,它 ...
随机推荐
- mongo日常操作备忘
修改 普通修改 插入数据: db.students.insert({ "name":"swrd", "age":32, "grad ...
- apache的作用和tomcat的区别
经常在用apache和tomcat等这些服务器,可是总感觉还是不清楚他们之间有什么关系,在用tomcat的时候总出现apache,总感到迷惑,到底谁是主谁是次,因此特意在网上查询了一些这方面的资料,总 ...
- rn初体验
react-native 需要的工具 .nodejs .rn cli .xcode and as ---------------- 打开终端,切换到根路径(mac中修改npm的默认安装来源) 一.op ...
- 我的CCF备考指南
CCF计算机软件能力认证(简称CCF CSP认证). 认证涉及知识点: 认证内容主要覆盖大学计算机专业所学习的程序设计.数据结构.算法以及相关的数学基础知识.包括但不限于: (1)程序设计基础 逻辑与 ...
- java线程的常用方法和属性介绍
start() start方法是Thread 类的方法,在这个方法中会调用native方法(start0())来启动线程,为该线程分配资源. sleep() sleep方法有2个方法. public ...
- SourceTree for mac 注册过程(v2.7.6a)
背景 为啥要自己注册呢,往上一堆一堆的老版本许可证偏不用,就愿意定制自己的账号style. 搞了半天,还是觉得pycharm自带的git工具就挺好用了,闲的没事记录一下. 要点 百度搜索的地址可以进入 ...
- 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)
题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...
- python初步学习-python数据类型之number(数值)
数据类型之 Number python number 数据类型用于存储数值. 数据类型是不容许改变的. 这就意味着如果改变 number 数据类型的值,将重新分配内存空间. python支持四种不同数 ...
- VMware 12安装虚拟机Mac OS X 10.10使用小技巧(虚拟机Mac OS X 10.10时间设置,虚拟机Mac OS X 10.10通过代理上网,Mac OS X 10.10虚拟机优化,VMware虚拟机相互复制)
1:修改Mac OS 系统时间 2:Mac OS系统 通过代理上网 VMware 12安装Mac OS X 10.10虚拟机优化心得 虚拟显卡硬伤,所以必须要优化下才能用,优化的原则就是能精简的精简, ...
- 父元素与子元素之间的margin-top问题(css hack)
hack: 父元素的盒子包含一个子元素盒子,给子元素盒子一个垂直外边距margin-top,父元素盒子也会往下走margin-top的值,而子元素和父元素的边距则没有发生变化. hytml代码: &l ...