简单来说,因为js是单线程的,所以出现了Event Loop。原因即单线程一次只能执行一个任务,如果有多个任务,就需要排队,执行完一个再执行下一个,这样会造成资源的浪费,造成‘假死’的情况。并且js没有锁机制,多线程将会使DOM操作变得不可控(当然目前已有新的API,web woker来实现多线程)。Event Loop(事件循环)是浏览器或Node的解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。
Event Loop是一个程序结构,负责等待和发送消息和事件。JS 在执⾏的过程中会产⽣执⾏环境,这些执⾏环境会被顺序的加⼊到执⾏栈中。如果遇 到异步的代码,会被挂起并加⼊到 Task (有多种 task) 队列中。⼀旦执⾏栈为空, Event Loop 就会从 Task 队列中拿出需要执⾏的代码并放⼊执⾏栈中执⾏,所以本质上来 说 JS 中的异步还是同步⾏为。
⼀次 Event loop 顺序是这样的:
即微任务优先于宏任务执行。
Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。JS调用栈采用的是后进先出的规则,当函数执行的时候,会被添加到栈的顶部,当执行栈执行完成后,就会从栈顶移出,直到栈内被清空。
- 堆:是一种数据结构,是利用完全二叉树维护的一组数据,堆分为两种,一种为最大堆,
- 一种为最小堆,将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
- 堆是线性数据结构,相当于一维数组,有唯一后继。
-
- 栈:也是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据
- 在栈顶,需要读数据的时候从栈顶开始弹出数据。栈是只能在某一端插入和删除的特殊线性表。
- 没有了位置概念,保证任何时候可以访问、删除的元素都是此前最后存入的那个元素,确定了一
- 种默认的访问顺序。
-
- 队列:是一种操作受限制的线性表,只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
在JavaScript中,任务被分为两种,一种宏任务(MacroTask)也叫Task,一种叫微任务(MicroTask)。
常见的宏任务:
script全部代码、setTimeout、setInterval、setImmediate(浏览器暂时不支持,只有IE10支持,具体可见MDN)、I/O、UI Rendering。常见的微任务:
Process.nextTick(Node独有)、Promise、Object.observe(废弃)、MutationObserver(具体使用方式查看这里)Javascript单线程任务被分为同步任务和异步任务,同步任务会在调用栈中按照顺序等待主线程依次执行,异步任务会在异步任务有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。