js的事件循环(Event loop)、执行上下文、执行栈和事件队列的手记

js是一个单线程非阻塞的脚本语言。
单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务。
非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调。
为什么要单线程?因为js是和浏览器交互的,需要操作各种dom, 如果javascript是多线程的,那么当两个线程同时对dom进行一项操作,例如一个向其添加事件,而另一个删除了这个dom,此时该如何处理呢?因此,为了保证不会 发生类似于这个例子中的情景,javascript选择只用一个主线程来执行代码,这样就保证了程序执行的一致性。
非阻塞如何实现,通过--------event loop(事件循环)。

执行栈(先进后出):
当一个js文件执行的时候,会产生一个全局执行上下文,每调用一个函数会产生一个新的执行上下文,全局执行上下文会先放入栈中,然后执行一个函数时会把这个上下文放进栈中,然后进入函数中进行执行,遇到新的函数执行会把新的执行上下文再次放入栈中,然后执行函数里面的代码,知道代码执行完毕,会把对应执行上下文(出栈)销毁,等待垃圾回收。
全局上下文只有唯一的一个,它在浏览器关闭时出栈。

console.log(1);

function pFn() {
    console.log(2);
    (function cFn() {
        console.log(3);
    }());
    console.log(4);
}
pFn();

console.log(5);
//输出:1 2 3 4 5

在这里插入图片描述
以上的过程说的都是同步代码的执行。

那么当一个异步代码(如发送ajax请求数据)执行后会如何呢?前文提过,js的另一大特点是非阻塞,实现这一点的关键在于下面要说的这项机制——事件队列(Task Queue)。
遇到js异步事件不会马上执行,会把这个异步事件挂起,接着执行 执行栈中的其他任务。当一个异步事件返回结果后,js会把这个异步事件放入事件队列(先进先出)中,被放入的异步事件不会马上执行,而是等待当前执行栈中的所有任务都执行完毕, 主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码,这样就形成了一个无限的循环。这就是这个过程被称为“事件循环(Event Loop)”的原因。
在这里插入图片描述
stack表示我们所说的执行栈,web apis则是代表一些异步事件,而callback queue即事件队列。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值