大师课干货笔记 | 第一章:事件循环原理

浏览器的进程及JavaScript执行的原理详解

JavaScript是一门单线程的语言,它的执行方式是异步的。在浏览器中,JavaScript的运行是在渲染进程中完成的。而浏览器中还有其他进程,如浏览器主进程和插件进程,它们负责协调和控制整个浏览器的工作。本文将详细介绍浏览器进程以及JavaScript的执行原理。

浏览器的进程

浏览器的进程大致可以分为以下三个:

  1. 渲染进程(Renderer Process):负责网页的渲染,包括 HTML、CSS 和 JavaScript 的解析执行,以及页面布局和绘制等工作。

  2. 插件进程(Plugin Process):负责插件的运行,如 Flash 插件、视频播放插件等。

  3. 浏览器主进程(Browser Process):负责协调和控制整个浏览器的工作,包括页面的导航、标签页的管理、扩展程序的运行、插件的管理和垃圾回收等。

浏览器主进程是第一个启动的进程,剩余的进程都是由它调用的。渲染进程可以有多个,每个标签页对应一个渲染进程。

JavaScript执行的原理

JavaScript的执行主要是在渲染进程中完成的。但是渲染进程不仅负责JavaScript的执行,还有很多其他的任务,例如渲染、HTML、CSS、定时器、网络请求等等。那么它是如何执行JavaScript的呢?

  1. 队列

渲染进程中会有一个“人”一直在操作生产线上的代码,也就是执行队列。队列中包括渲染任务、定时任务、网络任务、点击事件任务等。JavaScript执行的代码也会被加入到队列中等待执行。

JavaScript代码示例:

 

javascript复制插入

setTimeout(function(){
    console.log('异步定时任务1');
}, 0);

console.log('同步代码');

setTimeout(function(){
    console.log('异步定时任务2');
}, 0);

复制插入

执行结果:

同步代码
异步定时任务1
异步定时任务2

上面的代码中,两个定时任务被添加到队列中,但是由于定时器时间设为0,所以会立即执行。

  1. 异步执行

JavaScript是单线程的,也就是说只有一个主线程,它只能顺序执行代码。如果执行一个任务时需要等待,那么会阻塞后续任务的执行。为了避免这种情况,JavaScript采用异步执行的方式。

例如,在执行一个定时任务时,JavaScript不是自己盯着时间进行计算的,而是交给其他线程模块进行计时。时间到了后,模块会把任务放到队列中,等待主线程空闲时执行。网络请求、点击事件等也是类似的情况,不会立即执行,而是被相应的模块放到队列中等待执行。

JavaScript代码示例:

 

javascript复制插入

setTimeout(function(){
    console.log('异步定时任务1');
}, 1000);

console.log('同步代码');

setTimeout(function(){
    console.log('异步定时任务2');
}, 2000);

复制插入

执行结果:

同步代码
异步定时任务1
异步定时任务2

上面的代码中,两个定时任务被添加到队列中,并且定时器时间都比较长,所以会等待一定的时间再执行。

  1. 任务类型的优先级

现在大部分浏览器都抛弃了只有宏队列和微队列的做法,而是根据任务类型的优先级来执行。不同的任务类型有不同的优先级,例如,Promise是微队列中的任务,它的优先级最高,必须要优先执行。

JavaScript代码示例:

 

javascript复制插入

setTimeout(function(){
    console.log('异步定时任务1');
}, 0);

Promise.resolve().then(function(){
    console.log('微队列中的任务');
});

setTimeout(function(){
    console.log('异步定时任务2');
}, 0);

复制插入

执行结果:

微队列中的任务
异步定时任务1
异步定时任务2

上面的代码中,两个定时任务被添加到宏队列中,而Promise则被添加到微队列中。由于微队列优先级最高,所以会先执行微队列中的任务,再执行宏队列中的任务。

  1. 优先执行函数全局任务

在一次事件循环中,主线程会先执行函数全局任务,也就是当前的所有任务。比如,代码中设置定时器一秒钟打印1,那么主线程会先打印所有1再执行定时器的打印。

JavaScript代码示例:

 

javascript复制插入

setTimeout(function(){
    console.log('异步定时任务');
}, 1000);

for(var i=0; i<5; i++){
    console.log('同步打印', i);
}

复制插入

执行结果:

同步打印 0
同步打印 1
同步打印 2
同步打印 3
同步打印 4
异步定时任务
  1. 浏览器实现计时器的精度问题

在JavaScript中,计时器的精度问题是无法避免的。主要有以下原因:

  • 计算机硬件没有原子钟,无法做到准确的计时。
  • 操作系统的计时函数本身就有一定的偏差,不同的操作系统计时器有少量的差异。
  • 按照W3C的标准,浏览器实现计时器时,如果嵌套层级超过5层,则会产生4毫秒的最小误差。

上面的代码中,计时器设置的时间为1秒钟,但是实际上会有一定的误差(约为1毫秒)。

  1. 其他进程的任务执行

其他进程也会有自己的任务队列,主进程会执行主队列。其他进程根据优先级不同,将任务添加到主队列中进行执行。由于这部分内容比较底层,这里就不举例子了。

总结

JavaScript的执行是基于事件循环的异步执行方式,主要执行在浏览器的渲染进程中。在执行JavaScript代码时,会将任务加入到队列中等待异步执行,而队列中的任务会根据任务类型的优先级进行执行。为了保证计时的精度,JavaScript计时器的实现方式采用了一定的容错机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值