JS运行机制

JS的单线程

单线程是JS语言的一大特点,通俗的理解就是同一时间只能做一件事情。为什么JS是单线程呢?这与它的用途有关,作为浏览器脚本语言,JS的主要用途是与用户互动,以及操作DOM。如果是多个线程同时操作一个DOM,比如一个线程需要隐藏DOM,一个线程需要显示DOM,就会出现混乱,不知道先执行的哪个,达不到想要的效果,但如果是单线程,就很简单的实现了我们想要的效果,所以为了避免复杂性,就诞生了JS是单线程。
HTML5提出Web Worker标准,允许JS脚本创建多个线程,但是子线程完全受主线程控制,且不能操作DOM.所以这个新标准并没有改变JS单线程的性质。

任务队列

"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。但是,由于存在"定时器"功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。
所有任务可以分成两种:

  1. 同步任务
    在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  2. 异步任务
    不进入主线程,而进入“任务队列”的任务,只有“任务队列“通知主线程,某了异步任务可以执行了,该任务才会进入主线程执行。
    3.异步执行的运行机制
    (1)所有同步任务都在主线程上执行,形成一个执行栈。
    (2)主线程之外,还存在一个”任务队列“,只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
    (3)一旦”执行栈“中的所有同步任务执行完毕,系统就会读取”任务队列”看看里面有哪些事件。那些对象的异步任务,于时结束等待状态,进入执行栈,开始执行。
    (4)主线程不断重复上面的第三步。
Event Loop(事件轮询)

主线程从“任务队列”中读取事件,这个过程是循环不断的,所以这个的这种运行机制又称为Event Loop (事件轮询)
宏任务进入主线程,执行完之后,查看微任务中是否有可以执行的函数,有就执行,第一次事件循环就结束,查看是否还有宏任务,有就开始执行第二轮,执行完宏任务之后,再查看微任务中是否有可执行代码,有就执行,第二轮事件循环结束,一直这样子循环,就是事件轮询。

常见的JS机制面试题
console.log(1);
setTimeout(function(){console.log(2);},0);
console.log(3)

以上代码的执行结果为 1,3,2。因为setTimeout是一个异步任务,只有当同步任务console.log(1)console.log(3)执行完的时候,才会去执行异步任务的代码。

console.log('A');
setTimeout(function(){console.log('B');},0);
while(1){}

以上代码的执行结果为A,跟上题原理差不多的,先执行console.log(‘A’);,遇到setTimeout之后放到任务队列中,往下执行while(1){},这就会导致无限循环段代码,执行不完,所以setTimeout就没法执行,只能打印出A。

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

以上代码的执行结果为 i的值为4,因为for循环是一个同步任务,当它遇到setTimeout的时候,会放入任务队列必不会执行里面的代码。比如 i= 0 的时候,遇到setTimeout将setTimeout函数放入任务队列中,继续下一次循环,i=1的时候,又将setTimeout放入任务队列,如此循环,当for循环执行完毕,也就意味主线程的代码被执行完,1秒后可以执行任务队列的代码,此时任务队列已经存放4个setTimeout函数,并且此时的i的值为4,所以控制台会输出四遍4.

注:当代码耗时很长的时候,有可能要等很久,所以并没有办法保证,回调函数一定会在setTimeout()指定的时间执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值