JS的执行机制
JS是单线程
JS是单线程的,也就是说JS代码是按顺序执行的,一行一行执行的,不会出现同时执行多行代码的情况。
也就是JavaScript同一时间内只能做一件事情,如果有多个任务,就必须排队,前一个任务结束,才能执行后一个任务。(比如我们对某个DOM元素进行添加删除操作室,不同同时进行,要按照顺序执行)
这样就会导致一个问题:如果js执行时间过长,就会给用户一种页面加载很慢的感觉(页面渲染不连贯,页面加载阻塞)。
为了解决这样一个问题,HTML5提出了Web Worker标准,允许JavaScript脚本创建多个线程,于是出现了JS的同步和异步。
同步
同步就是按照顺序执行,前一个任务结束,才能执行后一个任务。
程序执行的顺序与代码的顺序是一致的、同步的。
同步任务都放在主线程上执行,形成了一个执行栈
。
console.log('1'); setTimeout(function(){ console.log('2'); },0); console.log('3'); 复制代码
在上面的代码中,同步任务有:
同步任务 |
console.log('1'); |
setTimeout(function(),0); |
console.log('3'); |
其中setTimeout里面的函数异步任务,它会在主线程上执行完同步任务后,将异步任务放到任务队列
中,等待主线程空闲后,再执行。
异步
异步就是不按照顺序执行,前一个任务结束,不一定要执行后一个任务。
JavaScript的异步是通过回调函数来实现的。
异步任务我们放在任务队列(消息队列)里面。
常见的异步任务有以下三类:
- 普通事件:比如click、scroll、mousemove等
- 资源加载:比如图片加载、音频加载、文件加载等
- 定时器:比如setTimeout、setInterval等
二者的本质区别就是在程序在条流水线上各个流程的执行顺序不同。
执行机制
- 先执行
执行栈里面的同步任务
。 - 如果遇到异步任务,就将异步任务放到
任务队列
中。继续执行下面的同步任务。 - 当执行栈里面的同步任务执行完毕,就会将任务队列里面的异步任务按照次序放到执行栈中执行。
在主线程将异步任务添加到任务队列的过程中,有一个异步进程处理,当带有异步任务的同步任务执行完毕之后才会添加到任务队列中。
当主线程执行完毕之后,会去任务队列中取出异步任务,放到执行栈中执行。去任务队列获取异步任务的这个过程,会一次又一次的执行。
也就是主线程不断的重复获得任务、执行任务、再获取任务、在执行任务、、、,这种机制就被成为事件循环
。