JavaScript 执行机制-浏览器事件循环

大多数时候,我们去面试,都会遇到,让你说出一段代码的执行结果,或者说出其执行顺序。因为javascript是单线程的。

关于javascript

javascript 是一门单线程语言,最新的H5中提出了webworker,但是单线程这个核心没有发生改变。一切javascript“多线程”都是单线程模拟出来的,所有新线程都受主线程的控制,不能独立执行。意味着,这些线程是主线程的“子线程”,此外,这些线程没有执行IO的权限,只能为主线程分担一些计算任务。

javascript事件循环

javascript是单线程的,那么js任务就需要一个一个的按顺序来执行。如果一个任务耗时过长,后面一个任务就需要等待,不过这并不是一件总能让人接受的事情,如果我们在看一篇文章,文章中部有一张超清图片,那么我们的文章要等到图片加载完之后,才能加载后面的文字,是不是要疯了~

为了解决这种尴尬,js将任务分成两类:

  • 同步任务
  • 异步任务

当我们打开网站,网页渲染就是一大推的同步任务,比如 html 骨架,css。 而加载视频,音乐,图片等占资源耗时较长的,就是异步任务。

javascript 宿主

目前主要应用为两种,一种是浏览器javascript,一种是node,他们的事件循环也是不一样的。

浏览器下的js事件循环机制

执行栈和事件队列

javascript代码执行时,会将不同变量存在于不同位置:中加以区分。堆中存放对象,栈中存放基础类型变量和对象指针。

执行栈 和上面所说的栈还不一样,当我们调用一个方法时,js会生成与这个方法相对应的执行环境(context),也叫做“执行上下文”。这个执行环境中,存在这个方法的私有作用域,上层作用域指向,方法参数,在这个作用域中定义的变量还有这个作用域的this对象,而当一系列的方法被调用,js还是单线程,同一时间只能执行一个方法,于是,这些方法被“排成队”放在一个地方,就是执行栈

当一个脚本执行,js引擎解析这段代码,同步代码按顺序加入执行栈,然后开始从头执行,当前执行一个方法,js向执行栈添加当前方法的执行环境,进入执行环境继续执行其中代码,当这个环境中的代码执行完毕返回结果后,js退出这个执行环境,并将这个环境销毁,回到上一个方法的执行环境,反复进行这个过程,直到执行栈中全部代码执行完毕。

事件队列 以上说的都是同步代码执行,那么异步代码执行会如何呢?js是非阻塞的,就是靠事件队列这项机制来实现。

js引擎遇到一个异步事件,不会傻傻的等待事件返回,而是先将其挂起,然后继续执行栈中其他任务。当一个异步事件返回结果后,js将这个事件加入到“事件队列”,被放入事件队列的不会立即执行回调,而是要等待当前栈中所有任务都完成之后,主线程闲下来了,然后去看看事件队列是不是有任务,有的话,就从中取出排在第一位的事件的回调,放入执行栈,执行其中的同步代码,如此反复,无限循环,称为“事件循环”。

macro task 和 micro task

以上我们对事件循环是一个宏观的表述,实际上,异步任务也不一样,执行优先级也有不同,不同的异步任务被分为两类“宏任务”(macro task)和“微任务”(micro task)

宏任务

  • setInterval()
  • setTimeout()

微任务

  • new Promise()
  • new mutaionObserver()

在一个时间循环中,异步事件返回结果被放到一个任务队列,根据异步事件的类型,会被放到相应的“宏任务队列”和“微任务队列”,当前执行栈为空时,主线程会先查微任务是否有事件存在,如果不存在,再去宏任务队列取出一个事件,加入当前执行栈;如果存在,依次执行队列中事件对应的回调,直到微任务队列为空,然后再去执行宏任务队列事件回调。

同一次事件循环中,微任务永远领先宏任务执行。

setTimeout(function () {
    console.log(1);
});

new Promise(function(resolve,reject){
    console.log(2)
    resolve(3)
}).then(function(val){
    console.log(val);
})
// 2 3 1
复制代码

转载于:https://juejin.im/post/5ca484956fb9a05e146d7205

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值