Jason
Jason
 结合以下描述,看图理解。
JavaScript 是单线程、非阻塞的脚本语言,单线程指同一个时间只能做一件事。 JavaScript 的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。 而非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调。 JavaScript 的任务分两种:一种是同步任务(synchronous),另一种是异步任务(asynchronous)。 同步任务指的是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有某个异步任务可以执行了,该任务才会进入主线程执行。 ### 理解 Event Loop JavaScript 的运行机制如下: - 所有同步任务都在主线程上从头开始执行,将当前的执行环境压入执行栈(execution context stack)等待执行,如果是一个方法,则加入执行栈的是当前方法的执行环境(私有作用域、上层作用域的指向、参数、变量和this等) - 在主线程之外,存在一个"事件队列",当某个异步任务达到可执行的状态时,就推入到"事件队列"之中 - 当"执行栈"中的所有同步任务执行完毕,系统就会读取"事件队列"。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行 主线程不断重复上面的第三步。所以整个的这种运行机制又称为 Event Loop(事件循环)。只要主线程空了,就会去读取"事件队列",这就是 JavaScript 的运行机制。 > 事件队列包括:Task...
浏览器为了能够使得 JS 内部 Macrotask 与 DOM 任务能够有序的执行,会在一个 Macrotask 执行结束后,在下一个 Macrotask 执行开始前切换至 UI 线程,对页面进行重新渲染,流程如下: ``` (macro)task->渲染->(macro)task->... ``` 在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下: - 执行一个宏任务(栈中没有就从事件队列中获取) - 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中 - 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行) - 当前宏任务执行完毕,执行完当前所有微任务,开始检查渲染,然后 GUI 线程接管渲染...
# node环境下的事件循环机制 事件循环的模型: ``` ┌───────────────────────┐ ┌─>│ timers │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ │ │ I/O callbacks │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ │ │ idle, prepare │ │ └──────────┬────────────┘ ┌───────────────┐ │...
[全方位解读前端用到的栈结构(调用栈、堆、垃圾回收等)](https://github.com/sisterAn/JavaScript-Algorithms/issues/24)
[Mobx真的好用吗?它有什么优缺点?主要适用于什么场景?](https://www.zhihu.com/question/328612405)
[浏览器渲染流程 详细分析](https://juejin.im/entry/59f010fdf265da4315231caa) > 内容较多,特别是 demo 讲得不错
扩展阅读:[从 8 道面试题看浏览器渲染过程与性能优化](https://github.com/webfansplz/article/issues/39)
[前端代码如何通过浏览器演化为屏幕显示的像素](https://zhuanlan.zhihu.com/p/44737615)
[网站性能优化实战——从12.67s到1.06s的故事](https://www.imweb.io/topic/5b6fd3c13cb5a02f33c013bd) [网站性能优化实战(二)](https://www.imweb.io/topic/5b4d417eee0c3b0779df96d9) [如何不择手段提升scroll事件的性能](https://zhuanlan.zhihu.com/p/30078937)