JS-运行机制

参考自:https://juejin.im/post/6844903805063004167 和 https://www.cnblogs.com/fly_dragon/p/8669057.html,如有侵权,请联系删除。

一  JavaScript 单线程

浏览器多线程:

  GUI渲染线程:负责渲染HTML元素,与JS引擎线程是互斥的,当执行JS脚本时,GUI渲染线程被挂起。

  JS引擎线程:负责解析和执行JS脚本,与GUI线程是互斥的,一个tab页无论何时都只有一个JS线程在运行JS程序。

  事件触发线程:用来控制事件轮训,当JS代码中触发了DOM的事件,会将事件对应的任务添加到事件触发线程的任务队列中,直到JS引擎空闲下来再按照队列的顺序逐一处理事件触发线程的任务。

  定时器线程:setInterval与setTimeout所在的线程,该线程完成定时器的定时。

  异步http请求线程:在XMLHttpRequest在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript引擎的处理队列中等待处理。

JS单线程:即上述JS引擎单线程。为什么要单线程?因为多线程处理DOM会产生冲突,虽然可以加锁机制但是所机制,单会带来更大的复杂性。

 

#为了多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
#JS 引擎只是任意的 JS 代码按需执行的环境。是它周围的环境来调度这些事件(JS 代码执行)。,其他周围环境就是指的在同一进程下的不同的线程,比如事件触发线程、定时器线程等(JS引擎是被宿主环境调度去执行JS的)

二  任务队列

任务队列:队列里面存放着各种任务和事件。

  宏任务队列macro-task,在ES5中又称为task。

  微任务队列micro-task,在ES5中又称为job。

任务:

  同步任务synchronous,按照队列顺序阻塞式执行的

  异步任务asynchronous非阻塞式执行的,使用场景:应用于任务耗时较长或者不确定的场景。常见的异步任务:1.DOM事件 2. setTimeout 3.setInterval 4.异步函数

三  setTimeout 和 setInterval 的运行机制

setTimeout 和 setInterval的运行机制:将指定的代码移出本次Event loop 执行。等本次同步代码执行完以后,判断是否到达设定时间,如达到设定时间则执行setTimeout 和 setInterval 中的代码,若未达到设定时间,等待下一轮Event loop继续判断。

类似案例:addEventListener()方法监听点击事件click,点击进入“假死”状态,其实就是等待队列中的同步任务执行完成,才能够执行异步代码。

 

案例一:输出结果为: ‘A’,因为任务队列中的同步任务代码陷入死循环,无法执行到异步任务。

console.log('A');

setTimeout(function () {

  console.log('B');

}, 0);

while (1) {}

案例二:输出结果为: 4 4 4 4

for (var i = 0; i < 4; i++) {

   setTimeout(function () { //执行到异步任务时,只是将异步任务交给定时器(即使设置为0,也是4s),当定时时间到,定时器把异步任务交给异步队列。

    console.log(i); //执行此步时,for同步代码已经执行完成,i传入4次故此时的i=4

   }, 1000);

}

案例三:输出结果为: 1 2 3 4 ,let 可定义块级作用域变量,每次for循环的循环体,都是一个全新独立的块作用域,let声明的变量传到for循环体内以后,作用域外部无法更改

for (let i = 0; i < 4; i++) {

   setTimeout(function () {   //执行到异步任务时,只是将异步任务交给定时器(即使设置为0,也是4s),当定时时间到,定时器把异步任务交给异步队列

    console.log(i); //执行此步时,for同步代码已经执行完成,但是每次传入的let i无法被其他循环代码更改,保持1 2 3 4 

   }, 1000);

}

 

posted on 2020-10-16 15:09  挣扎的发际线  阅读(91)  评论(0编辑  收藏  举报

导航