js引擎是单线程执行的
js语言设计的一个很重要的点是,
js是没有多线程的.js引擎的执行是单线程执行
.这个特性曾经困扰我很久,我想不明白既然js是单线程的,那么是谁来为定时器计时的?是谁来发送ajax请求的?我陷入了一个盲区.即将js等同于浏览器.我们习惯了在浏览器里面执行代码,却忽略了浏览器本身.js引擎是单线程的,可是浏览器却可以是多线程的,js引擎只是浏览器的一个线程而已.定时器计时,网络请求,浏览器渲染等等.都是由不同的线程去完成的.
var isStop = true;
setTimeout(function () {
isStop= false;
}, 500);
while (isStop);
alert('END');
isStop默认是true的,在while中是死循环的.最后的alert是不会执行的. 我添加了一个定时器,1秒后将isStop改为false. 如果说js引擎是多线程的,那么在1秒后,alert就会被执行.然而实际情况是,页面会永远死循环下去.alert并没有执行.这很好的证明了,
settimeout并不能作为多线程使用.js引擎执行是单线程的
.
js事件的驱动
先看图
![](http://images2015.cnblogs.com/blog/596947/201604/596947-20160424200428195-1086416163.jpg)
针对上图理解:
js引擎单线程执行的,它是基于事件驱动的语言.它的执行顺序是遵循一个叫做事件队列的机制.从图中我们可以看出,浏览器有各种各样的线程,比如事件触发器,网络请求,定时器等等.线程的联系都是基于事件的.js引擎处理到与其他线程相关的代码,就会分发给其他线程,他们处理完之后,需要js引擎计算时就是在事件队列里面添加一个任务. 这个过程中,js并不会阻塞代码等待其他线程执行完毕,而且其他线程执行完毕后添加事件任务告诉js引擎执行相关操作.这就是js的异步编程模型.
看个setTimeout的例子:
alert("start");
setTimeout(() => {
alert("done");
}, 0);
alert("end");
这是一个很简单的实验,如果settimeout(0)会立即执行,那么这里的执行结果就应该是start、done、end . 然而实际的结果却是start、end、done
对于这个结果我们的解释是:
js代码执行到这里时,会开启一个定时器线程,然后继续执行下面的代码.该线程会在指定时间后往事件队列里面插入一个任务.由此可知settimeout(0)里面的操作会放在所有主线程任务之后. 这也就解释了为什么第一个实验结果是start、end、done .
给出最终结论为:
在指定时间内, 将任务放入事件队列,等待js引擎空闲后被执行.
js引擎与GUI引擎是互斥的
谈到这里,就不得不说浏览器的另外一个引擎---GUI渲染引擎. 在js中渲染操作也是异步的.比如dom操作的代码会在事件队列中生成一个任务,js执行到这个任务时