js onclick传参数_前端开发浏览器技术秘籍 (四)浏览器JS运行机制

本文详细介绍了浏览器的多进程与多线程模型,强调JavaScript引擎的单线程特性及其对异步处理的影响。JavaScript的执行通过事件循环机制,处理同步任务和异步任务的队列,如定时器、Ajax事件和用户行为。当执行栈为空时,事件循环会从任务队列中取出任务执行,从而实现无阻塞加载。文章还讨论了常见的异步任务类型,如定时器、Ajax请求和用户交互事件。
摘要由CSDN通过智能技术生成

17aec32fe1df52ff6c597512fa35b44d.png

前言:

贝程学院:前端开发浏览器技术秘籍 (二):浏览器中的多进程与多线程​zhuanlan.zhihu.com
a7f2b48dc6586b713737670ae03c84ad.png

在前文写到浏览器内核是多线程的,它们在内核控制下相互配合并保持同步,一个浏览器中至少有三个常驻线程:JavaScript引擎线程,GUI渲染线程,浏览器事件触发线程。

其中JavaScript引擎属于单线程作业。所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个,也不妨叫它主线程。JavaScript引擎由于是单线程作业,意味着:在同一时间只能执行一个代码块,这些代码块的执行就阻塞了异步事件的处理。

一.JavaScript是单线程

因为JS运行在浏览器中,是单线程的,每个 Window一个JS线程,既然是单线程的,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码。而浏览器是事件驱动的(Event driven),浏览器中很多行为是异步(Asynchronized)的,会创建事件并放入执行队列中。javascript引擎是单线程处理它的任务队列,你可以理解成就是普通函数和回调函数构成的队列。当异步事件发生时,如mouse click, a timer firing, or an XMLHttpRequest completing(鼠标点击事件发生、定时器触发事件发生、XMLHttpRequest完成回调触发等),将他们放入执行队列,等待当前代码执行完成。

1.异步事件驱动

浏览器是事件驱动的(Event driven),浏览器中很多行为是异步(Asynchronized)的,例如:鼠标点击事件、窗口大小拖拉事件、定时器触发事件、XMLHttpRequest完成回调等。当一个异步事件发生的时候,它就进入事件队列。浏览器有一个内部大消息循环,Event Loop(事件循环)会轮询大的事件队列并处理事件。例如,浏览器当前正在忙于处理onclick事件,这时另外一个事件发生了(如:window onSize),这个异步事件就被放入事件队列等待处理,只有前面的处理完毕了,空闲了才会执行这个事件。setTimeout也是一样,当调用的时候,js引擎会启动定时器timer,大约xxms以后执行xxx,当定时器时间到,就把该事件放到主事件队列等待处理(浏览器不忙的时候才会真正执行)。

2.回调函数

回调函数英文定义:

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed。

从字面上的理解,回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。

其实也很好理解对吧,回调,回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数。

举一个别人举过的例子:

约会结束后你送你女朋友回家,离别时,你肯定会说:“到家了给我发条信息,我很担心你。” 对不,然后你女朋友回家以后还真给你发了条信息。小伙子,你有戏了。其实这就是一个回调的过程。你留了个参数函数(要求女朋友给你发条信息)给你女朋友,然后你女朋友回家,回家的动作是主函数。她必须先回到家以后,主函数执行完了,再执行传进去的函数,然后你就收到一条信息了。

四.JavaScript单线程技术原理

  1. 单线程意味着,【所有任务】都需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
  2. 如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。
  3. JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。
  4. 于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
  5. 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  6. 异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
  7. 具体来说,异步执行的运行机制如下。(同步执行也是如此,因为它可以被视为没有异步任务的异步执行。)
a.所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
b.主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
c.一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
d.主线程不断重复上面的第三步。

8.只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。

五.无阻塞加载JavaScript技术

无阻塞加载JavaScript技术,目的是为了提高页面呈现速度。由于JavaScript是单线程,在JavaScript运行时其他的事情不能被浏览器处理。事实上,大多数浏览器使用单线程处理UI更新和JavaScript运行等多个任务,而同一时间只能有一个任务被执行。所以在执行JavaScript时,会妨碍其他页面动作,这是JavaScript的特性。

html解析过程是至上而下的,当html解析器遇到诸如<script>、<link>等标签时,就会去下载相应内容。且加载、解析、执行JavaScript会阻止解析器往下执行。也就是当html解析器遇到<script>标签,无论它是内联还是外联,页面中的下载和解析过程都必须停止,直到<script>从外部加载进来的JavaScript或内联的JavaScript运行完毕,方可继续解析。在高版本的浏览器当中,允许并行下载JavaScript文件,当一个<script>标签正在下载外部资源时,不必阻塞其他<script>标签,但是不幸地是,JavaScript的下载仍然会阻塞其他资源的下载,例如图片。这里还需要值得注意的是,对于样式和脚本的先后顺序同样会影响到浏览器的解析过程,比如将<link>标签放在<script>标签前面,如果样式下载受阻,那么将阻塞<link>后面的<script>加载和执行,究其原因主要在于:script脚本在执行过程中可能会引用到相关样式。

六.什么是事件循环

事件循环(用于解决:异步问题/异步事件):在初期许多人会把异步理解成类似多线程的编程模式,其实他们中有着很大的差别,要完全理解异步,就需要了解 JS 的运行核心——事件循环(event loop)。

事件循环:【事件队列】是一个存储着待执行任务的队列,其中的任务严格按照时间先后顺序执行,排在队头的任务将会率先执行,而排在队尾的任务会最后执行。事件队列每次仅执行一个任务,在该任务执行完毕之后,再执行下一个任务。【执行栈】则是一个类似于函数调用栈的运行容器,当执行栈为空时,JavaScript引擎便检查事件队列,如果不为空的话,事件队列便将第一个任务压入中运行。

七.常见异步任务有那些

定时器任务(setTimeout();setInterval();)、Ajax事件浏览器/用户行为事件(例如:浏览器加载(load)、鼠标单击click、鼠标滑动/滑过/离开(mouseover、mouseout、mouseleave等).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值