11-3 JS的执行机制

先执行执行栈中的同步任务

异步任务(回调函数)放入任务队列中

一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

由于主线程不断的重复获得任务,执行任务,再获取任务,再执行,所以这种机制被称为“事件循环”(event loop)

1、javsscript语言是单线程?

javsscript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事,这是因为 javascript 这门脚本语言诞生的使命所致--javascript 是为处理页面中用户的交互,以及操作DOM而诞生的,比如我们对某个DOM 元素进行添加和删除操作,不能同时进行,应该先进行添加,之后再删除

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务,这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

同步和异步

     为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker 标准,允许JavaScript脚本创建多个线程,于是,js中出现了同步和异步。

    同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。

    异步:你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。

    它们的本质区别:这条流水线上各个流程的执行顺序不同

    同步任务:同步任务都在主线程上执行,形成一个执行栈

     异步任务:js 的异步任务事通过回调函数实现的。一般而言,异步任务有以下三种类型:

                       ①普通事件:如 click , resize等

                       ②资源加载:如 load , error 等

                       ③定时器:包括 setInterval , setTimeout等

                    异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)

2、js异步任务的类型?

①、普通事件:如 click , resize等

②、资源加载:如 load , error 等

③、定时器:包括 setInterval , setTimeout等

进程与线程

什么是进程

我们都知道,CPU是计算机的核心,承担所有的计算任务

官网说法,进程CPU资源分配的最小单位

字面意思就是进行中的程序,我将它理解为一个可以独立运行且拥有自己的资源空间的任务程序

进程包括运行中的程序和程序所使用到的内存和系统资源

CPU可以有很多进程,我们的电脑每打开一个软件就会产生一个或多个进程,为什么电脑运行的软件多就会卡,是因为CPU给每个进程分配资源空间,但是一个CPU一共就那么多资源,分出去越多,越卡,每个进程之间是相互独立的,CPU在运行一个进程时,其他的进程处于非运行状态,CPU使用 [时间片轮转调度算法](https://link.juejin.cn?target=undefined) 来实现同时运行多个进程

什么是线程

线程CPU调度的最小单位

线程是建立在进程的基础上的一次程序运行单位,通俗点解释线程就是程序中的一个执行流,一个进程可以有多个线程

一个进程中只有一个执行流称作单线程,即程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行

一个进程中有多个执行流称作多线程,即在一个程序中可以同时运行多个不同的线程来执行不同的任务, 也就是说允许单个程序创建多个并行执行的线程来完成各自的任务

进程和线程的区别

进程是操作系统分配资源的最小单位,线程是程序执行的最小单位

一个进程由一个或多个线程组成,线程可以理解为是一个进程中代码的不同执行路线

进程之间相互独立,但同一进程下的各个线程间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号)

调度和切换:线程上下文切换比进程上下文切换要快得多

JS为什么是单线程

JS的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

还有人说js还有Worker线程,对的,为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程是完 全受主线程控制的,而且不得操作DOM

所以,这个标准并没有改变JavaScript是单线程的本质

宏任务(macrotask) & 微任务(microtask)

宏任务(macrotask)

在ECMAScript中,macrotask也被称为task

我们可以将每次执行栈执行的代码当做是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行), 每一个宏任务会从头到尾执行完毕,不会执行其他

由于JS引擎线程GUI渲染线程是互斥的关系,浏览器为了能够使宏任务DOM任务有序的进行,会在一个宏任务执行结果后,在下一个宏任务执行前,GUI渲染线程开始工作,对页面进行渲染

宏任务 -> GUI渲染 -> 宏任务 -> ...

常见的宏任务

  • 主代码块
  • setTimeout
  • setInterval
  • setImmediate ()-Node
  • requestAnimationFrame ()-浏览器

微任务(microtask)

ES6新引入了Promise标准,同时浏览器实现上多了一个microtask微任务概念,在ECMAScript中,microtask也被称为jobs

我们已经知道宏任务结束后,会执行渲染,然后执行下一个宏任务, 而微任务可以理解成在当前宏任务执行后立即执行的任务

当一个宏任务执行完,会在渲染前,将执行期间所产生的所有微任务都执行完

宏任务 -> 微任务 -> GUI渲染 -> 宏任务 -> ...

常见微任务

  • process.nextTick ()-Node
  • Promise.then()
  • catch
  • finally
  • Object.observe
  • MutationObserver

 堆和栈的概念和区别

栈内存:

栈内存主要用来执行程序用的,存储的是局部变量和对象的引用,凡是定义在方法中的都是局部变量,for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,一旦离开作用域,变量就会被释放。栈内存更新的速度很快,因为局部变量的生命周期很短。

栈内存可以类似看做是一个矿泉水瓶,往里面放入东西,会马上沉入底部,所以它的特点是:

先进后出,后进先出

栈的存储速度比堆要快,仅次于寄存器,栈数据是可以共享,但是缺点是,存在栈中的数据大小和生存必须是确定的,缺乏灵活性

栈内存可以称为一级缓存,由垃圾回收器自动回收。

堆内存:

堆内存存储的是数组和对象(数组是特殊的对象),凡是new建立的都在堆里,堆中存放都是对象,对象用于封装数据,而且是封装多个属性,如果一个属性消失,这个实体也不会消失,还可以用,所以堆不会随时释放的。虽然对象不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的回收。

堆其实可以类似看做是管道,或者说是平时去排队买票,特点是:先进先出,后进后出

堆是在运行时动态分配内存的,存储速度较慢

堆内存可以称为二级缓存,堆中的对象不会随时释放,一般需要开发人员自己回收它

堆和栈的区别:

1. 栈内存存储的是局部变量,而堆内存存储的是实体对象。

2. 栈的更新速度要快于堆内存,因为局部变量的生命周期很短。 V栈 > V堆

3. 栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

4. 共享性不同,栈内存是线程私有的,堆内存是所有线程共有的。

5. 栈使用一级缓存,通常是被调用时处于存储空间,调用完立即释放。

    堆存放在二级缓存中,生命周期由虚拟机的垃圾回收算法决定。

6. 堆是先进先出,后进后出,栈是先进后出,后进先出

7. 栈的空间远远小于堆的空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值