线程
浏览器中有哪些进程呢?
1.浏览器进程:浏览器的主进程,负责浏览器的界面界面显示,与用户交互,网址栏输入、前进、后退,以及页面的创建和销毁。
2.渲染进程(浏览器内核):默认一个tab页面一个渲染进程,主要的作用为页面渲染,脚本执行,事件处理等。
3.GPU进程:用于3D绘制等,将开启了3D绘制的元素的渲染由CPU转向GPU,也就是开启GPU加速。
4.网络进程:主要负责页面的网络资源加载。
5.插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建。
6.音频进程:浏览器音频管理。
 
浏览器内核就是在渲染进程中,里面包含了多个引擎,它们拥有各自的线程。
GUI渲染线程
负责解析html, css。构建DOM树和RenderObject树。布局和绘制。
当页面元素中的某个dom节点有变化,需要绘制时,此线程就会执行。
JS引擎线程
它里面有个event loop和一个事件队列。这2者是JS引擎的核心基础。
拥有异步处理能力,JS引擎是单线程但可以实现异步并发处理事件,实现异步的基础是依靠上面的event loop和事件队列。H5的 Web Worker 标准规定,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制,且不得操作 DOM。所以,这个新标准并没有改变 JavaScript 单线程的本质。
它与GUI渲染线程互斥,用于处理页面交互和DOM更新,所以JS引擎线程和GUI渲染线程在处理任务时必须保证按顺序串行执行,一个执行另一个就要等待,这样才能保证每次页面渲染,更新都是确定的,不存在冲突。所以如果js处理的事件耗时,页面就会出现卡顿。
JS引擎主要负责处理JS脚本的词法分析,语法分拆,生成语法树,代码执行。内存管理,垃圾回收。
事件触发线程
监控各种事件的发生,比如用户的交互事件、页面DOM渲染完成事件等。当这些事件发生时,事件触发线程会将回调事件从定时器触发线程或者异步HTTP请求线程它们的事件队列中读取出来,放置到JS引擎的事件队列中,等待JavaScript引擎的执行。
辅助JS引擎线程管理事件队列,它和JS引擎线程是平级的关系。它的管理事件队列体现在将要处理的事件从其他线程队列中取出放到JS引擎的事件队列中。
定时器触发线程
用于专门做定时器计数用的,如果其他线程做这件事,可能会因为执行耗时任务而错过按时触发。
触发时机是当js引擎执行到setTimeOut, setInternal时,就会调用对应的webAPI,这些系统API内部都是将任务放置到定时器触发线程中进行处理,在线程中会把定时器事件以key:value的形式保存在event table中 方法名:回调函数 ,当回调时间到时,就将回调函数放置在自己的事件队列中,并发通知到事件触发线程,让事件触发线程将
事件放置到JS引擎的事件队列中。
异步HTTP请求线程
主要用于检测网络状态变化,如果检测到网络成功回调,则会把保存在自己event table中的回调事件放置到当前线程自己的事件队列中,然后通知,则会通知时间触发线程把处理回调函数放置到事件队列中。,并发通知到事件触发线程,让事件触发线程将
事件放置到JS引擎的事件队列中。
触发时机是当js引擎执行到ajax请求时,则会调用webAPI提供的接口,接口内部就会切换到异步HTTP请求线程中做网络事件的处理。
 
事件循环
 
事件循环主要解决了哪些问题?
1.避免耗时任务阻塞流程
html页面的加载是串行的,渲染进程解析HTML页面文件,碰到页面标签和css时,交给GUI渲染线程处理,碰到js标签时,则停止GUI渲染线程开始让js引擎处理js任务,如果要等耗时任务执行完再执行下面的任务,则卡主了页面。
2.增加了CPU执行效率
当JS引擎执行时碰到setTimeOut定时器事件,ajax网络事件时,都会调用webAPI让系统在专门的子线程进行处理,等到了回到时间,再把回调任务添加到js引擎的任务队列中,实现了耗时任务的同步执行。串行回调,增加了执行效率。
JS引擎的代码执行流程
1.JS引擎开始执行代码。
2.根据代码中的async,sync 同步、异步标识确定走同步流程还是异步流程。
3.同步流程是运行在JS引擎线程的,异步流程则是使用单独的线程进行处理,等处理完了将事件回调放置到JS引擎的事件队列中,让JS引擎进行执行。
4.当JS引擎执行完任务后会检查其任务队列中是否还有待处理的任务,如果有就继续出来,如果没有就停止等待。
js引擎存在一个monitoring process进程,它会持续不断的检查主线程执行栈是否为空,一旦检测到有任务就通知JS引擎取出任务执行。
任务的执行是按照任务进入队列的顺序进行的。任务的执行时间是受上一个任务的执行时长决定的,就像setTimeOut,方法里设置的是2秒后将回调放入js引擎的事件队列,但是任务的具体执行时间是不能确定的。

宏任务与微任务
setTimeOut, setInterval, async这样的是宏任务
progress.nextTick, Promise这样的是微任务,微任务是在执行宏任务的时候产生的,它存在全局上下文中。
宏任务与微任务的执行顺序是:宏任务 -> 微任务 -> 宏任务 -> 微任务 -> 空。
先执行宏任务,执行结束后。查看微任务队列中是否有微任务,有的话就执行,如果在执行微任务的过程中又产生了微任务,那么这个新的微任务会直接添加到当前执行的微任务队列。直到微任务队列中的任务都执行完才会开启下一轮宏任务->微任务循环。

JS执行上下文
 
JS执行上下文是JS代码执行的环境,JS代码的执行一定要在其执行上下文中。
全局执行上下文:浏览器中的全局上下文就是window, window是一个对象,全局上下文中的this指向的就是window。
函数执行上下文:每次函数的调用都会产生一个函数上下文,函数上下文内容包括:参数,局部变量的栈空间,堆空间。
上下文的生命周期如下:

上下文是一个对象,里面包含了变量对象VO,作用域链scopeChain,this对象。其基本结构如下:
ExecutionContext={
scopeChain:{},
VO:{},
this:{}
}
全局上下文变量对象
globalEC={
VO:window,
scopeChain:{},
this:window
}
函数上下文变量对象
function a(a,b){}
a(1,2)
innerTestEC={
VO={
arguments:{0:1,1:2,length:2}
a:undefined,
b:undefined
},// 变量对象
scopeChain:[VO(innerTest),VO(test),VO(global)],//作用域链
this:{}
}
参考文章:
https://juejin.cn/post/6844903512845860872
https://zhuanlan.zhihu.com/p/492563097

JS引擎中的线程,事件循环,上下文的更多相关文章

  1. 除了信号触发线程与接收者线程相同的情况能直接调用到slot,其它情况都依赖事件机制(解决上面代码收不到信号的问题其实很简单,在线程的run();函数中添加一个事件循环就可以了,即加入一句exec();),信号槽不就是一个回调函数嘛

    MainWindow::MainWindow(QWidget *parent) :   QMainWindow(parent)   {   pThreadCon = new CSerialThread ...

  2. Node.js event loop 和 JS 浏览器环境下的事件循环的区别

    Node.js  event loop 和 JS 浏览器环境下的事件循环的区别: 1.线程与进程: JS 是单线程执行的,指的是一个进程里只有一个主线程,那到底什么是线程?什么是进程? 进程是 CPU ...

  3. 浏览器中的JavaScript事件循环机制

    浏览器的事件循环机制是HTML中定义的规范. JavaScript有一个主线程和调用栈,所有的任务都会被放到调用栈等待主线程执行. JS调用栈 是一种先进后出的数据结构.当函数被调用时,会被添加到栈中 ...

  4. js 深入原理讲解系列-事件循环

    js 深入原理讲解系列-事件循环 能看懂这一题你就掌握了 js 事件循环的核心原理 不要专业的术语,说人话,讲明白! Q: 输出下面 console.log 的正确的顺序? console.log(' ...

  5. 【JavaScript】JS引擎中执行上下文如何顺序执行代码

    首先我们知道JavaScript引擎包括一个调用栈和堆,调用栈是代码实际执行的地方,使用执行上下文(执行环境)来完成:堆是非结构化的内存池,存储了应用程序所需要的所有对象. 执行上下文是什么? 执行上 ...

  6. JS执行环境栈及事件循环机制—简洁明了的讲解

    JavaScript解释器在浏览器中是单线程的,这意味着浏览器在同一时间内只执行一个事件,对于其他的事件我们把它们排队在一个称为 执行栈(调用栈) 的地方.下表是一个单线程栈的抽象视图: 我们已经知道 ...

  7. 转:10分钟了解JS堆、栈以及事件循环的概念

    https://juejin.im/post/5b1deac06fb9a01e643e2a95?utm_medium=fe&utm_source=weixinqun 前言 其实一开始对栈.堆的 ...

  8. VBS一键配置VOIP脚本(其中包括VBS操作JS网页中的按钮事件--直接执行确认按钮中的脚本代码)

    Dim ws,fso,IESet IE = WScript.createobject("InternetExplorer.Application")Set ws = WScript ...

  9. 详解JavaScript中的Event Loop(事件循环)机制

    前言 我们都知道,javascript从诞生之日起就是一门单线程的非阻塞的脚本语言.这是由其最初的用途来决定的:与浏览器交互. 单线程意味着,javascript代码在执行的任何时候,都只有一个主线程 ...

  10. js的事件循环和任务队列

    js 异步.栈.事件循环.任务队列 在开发中经常遇到js的异步问题,为了方便理解,记录下来,随时回顾. 以下的所有代码都是在浏览器环境下运行 在浏览器中js的运行是依赖浏览器js引擎来解析的,并且是在 ...

随机推荐

  1. 微软开源了一个 助力开发LLM 加持的应用的 工具包 semantic-kernel

    在首席执行官萨蒂亚·纳德拉(Satya Nadella)的支持下,微软似乎正在迅速转变为一家以人工智能为中心的公司.最近微软的众多产品线都采用GPT-4加持,从Microsoft 365等商业产品到& ...

  2. kafka rebalance你真的了解吗

    介绍 今天主要分享一下 kafka 的 rebalance,在 kafka 中,rebalance 是一个十分重要的概念,很多时候引发的一些问题可能都是由于 rebalance 引起的,rebalan ...

  3. 记一次 .NET 某手术室行为信息系统 内存泄露分析

    一:背景 1. 讲故事 昨天有位朋友找到我,说他的程序内存存在泄露导致系统特别卡,大地址也开了,让我帮忙看一下怎么回事?今天上午看了下dump,感觉挺有意思,在我的分析之旅中此类问题也蛮少见,算是完善 ...

  4. docker方式实现minio数据持久化离线安装

    保存镜像 root@hello:~# docker pull minio/minio Using default tag: latest latest: Pulling from minio/mini ...

  5. 五月十一号java基础知识点

    1.通过add()方法向链表list输入1-10十个数for (int i = 1; i <11 ; i++) { list.add(i);//向链表添加1-10的整数 } import jav ...

  6. 逍遥自在学C语言 | 位运算符&的高级用法

    前言 在上一篇文章中,我们介绍了&运算符的基础用法,本篇文章,我们将介绍& 运算符的一些高级用法. 一.人物简介 第一位闪亮登场,有请今后会一直教我们C语言的老师 -- 自在. 第二位 ...

  7. socket 到底是个啥

    哈喽大家好,我是咸鱼 我相信大家在面试过程中或多或少都会被问到这样一个问题:你能解释一下什么是 socket 吗 我记得我当初的回答很是浅显:socket 也叫套接字,用来负责不同主机程序之间的网络通 ...

  8. python+folium

    建模时无意中发现了一个很好用的交互式画地图的库!!

  9. 一文详解RocketMQ-Spring的源码解析与实战

    摘要:这篇文章主要介绍 Spring Boot 项目使用 rocketmq-spring SDK 实现消息收发的操作流程,同时笔者会从开发者的角度解读 SDK 的设计逻辑. 本文分享自华为云社区< ...

  10. 深度学习--实战 LeNet5

    深度学习--实战 LeNet5 数据集 数据集选用CIFAR-10的数据集,Cifar-10 是由 Hinton 的学生 Alex Krizhevsky.Ilya Sutskever 收集的一个用于普 ...