1、浏览器的进程:
进程:如QQ、微信等应用程序运行时都需要内存空间,可以简单将进程理解为内存空间,并且每个应用程序的内存空间是互相独立的,一个应用程序跑死不会影响其它应用程序。
浏览器的进程:有很多,如渲染进程、网络进程。
线程:每个进程都至少有一个主线程,线程可以理解为运行程序的“人”。渲染进程至少有一个渲染主线程。
2、异步(单线程是异步产生的原因)
JS是单线程的,因为它运行在浏览器的渲染主线程中。渲染主线程承担着诸多任务,渲染页面、执行JS等。
如果采用同步的方式,页面可能会由于长时间等待而造成卡死的现象,导致消息队列中的很多其它任务无法执行。
采用异步,浏览器将定时器任务等耗时的任务交给其它线程处理,自身立即结束此任务的执行,其它线程等时机成熟后(如等待时间到后)将回调函数包装成任务放在消息队列末尾等待主线程调度执行,这样不会造成阻塞的情况。
(注意:渲染主线程中的任务执行时有可能会产生新的任务放到消息队列末尾等待执行,如主线程在执行这一段代码:要修改页面上的一段文字,h1.textContent = 'bbb',这里修改后会产生一个新的渲染任务(就是要画到页面上,这是耗时的任务),将此渲染任务加到任务队列中。)如下代码:
const h1 = document.querySelector('h1')
const btn1 = document.querySelector('button')
function fn(){
//该函数很耗时,如等待3s
}
btn1.onclick('click',function(){
h1.textContent = 'bbb'
fn()
})
//当点击了按钮后,h1的文本内容要等待3s后才能变为bbb,这是因为,执行了修改h1文本这个任务后,又新生成了一个渲染任务,渲染主线程将这个渲染任务放到消息队列中,再去执行fn这个函数(耗时3s),执行完后,才去获取消息队列中的渲染任务执行。
3、事件循环(事件循环是异步的实现方式)
事件循环又称为消息循环,是浏览器渲染主线程的工作方式。
浏览器运行程序时,是开启一个无限循环,在每一次循环中,将全局JS放在渲染主线程中执行,其它的任务如setTimeout定时任务交给计时线程,到时间后计时线程将回调函数包装成任务放在延时任务队列中,用户点击事件的任务放在交互队列中。
W3C规定,每个任务都有一个任务类型,同类型的任务必须放在同一个队列中,不同类型的任务可以属于不同队列,不同任务队列有不同的优先级,在一次事件循环中,浏览器自行决定任务队列的优先级。但浏览器必须有一个微队列,微队列中的任务是优先级最高的(将任务加入微队列的方法其中之一:Promise.resolve().then(function))。当渲染主线程中的任务执行完后,从其它任务队列中获取任务执行。
如图: