跟着月影学 JavaScript & 事件循环知识点 | 青训营笔记

83 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第1天

课程核心

好的js代码的一些原则,主要是三大方面:

各司其责:让HTML、CSS和JavaScript职能分离。

组件封装:好的UI组件具备正确性、扩展性、复用性。

过程抽象:应用函数式编程思想。

分别举了三个例子来说明这三大原则如何理解运用

三大原则——各司其职

第一个深夜食堂的例子:用一个按钮修改日间/夜间模式(也就是页面样式)的例子,前后迭代了三个版本的代码,很直观地能看出代码是否优雅。

将结论大白话一下:

只有修改样式、纯展示,不涉及交互行为,数据传输的需求,最好追求零js方案。各司其职,class内写好不同模式下的样式,js只需要修改class名。

从第一个例子就能感受到,我们使用这些原则的场景和思路:如何重构代码,怎么让代码更加优雅,怎么让自己写的代码清晰好懂(为自己考虑也为同事考虑),后期修改需求时代码改动量小,实现功能的代码怎么样算是具有较高的复用性

三大原则——组件封装

第二个例子能够回答最后一个问题,同样迭代了两个版本,3种重构思路:

①重构:插件化——解耦

  • 将控制元素抽取成插件
  • 插件与组件之间通过依赖注入方式建立联系

比如说轮播图下方的点击圆点跳转至对应图片的功能是一个插件、两侧箭头点击切换轮播图功能也是一个插件,删除任何一个也不会影响其他功能的实现。

②重构:模板化——解耦

  • 将HTML模板化,更易于扩展

③组件框架——抽象

  • 将组件通用模型抽象出来

三大原则——过程抽象

介绍了过程抽象、高阶函数、编程范式这三大概念,并介绍了为什么要使用高阶函数、以及用户操作次数限制。

关于事件循环

我们首先需要了解js的运行机制和相关概念:

  • JS是单线程执行 ”JS是单线程的”指的是JS 引擎线程。
  • 宿主环境 JS运行的环境。一般为浏览器或者Node。
  • 执行栈 是一个存储函数调用的栈结构,遵循先进后出的原则。
  • 宏任务:由浏览器规定的
  • 微任务:由ES6语法规定的,放入微任务队列

Event Loop

JS到底是怎么运行的呢?

img

JS引擎常驻于内存中,等待宿主将JS代码或函数传递给它。 也就是等待宿主环境分配宏观任务,反复等待 - 执行即为事件循环。

调用栈清空后会不断地去(任务)消息队列取任务放到调用栈中

宏/微任务执行顺序

Event Loop中,每一次循环称为tick,每一次tick的任务如下:

  1. 执行栈选择最先进入队列的宏任务(一般都是script),执行其同步代码直至结束;
  2. 检查是否存在微任务,有则会执行至微任务队列为空;
  3. 如果宿主为浏览器,可能会渲染页面;
  4. 开始下一轮tick,执行宏任务中的异步代码(setTimeout等回调)。

image.png

每次执行完一次宏任务, (在调用栈为空的时候) ,事件循环会回去执行微任务,直到微任务队列清空才会执行下一轮宏任务并不会把宏任务全部执行了再执行微任务(这样可以避免宏任务繁重导致任务的阻塞),微任务队列清空后,浏览器可能会进行DOM渲染,渲染后再执行宏任务。

(seTimeout会等到script结束后才会执行回调,所以前面还有alert时,浏览器的渲染会被卡住,setTimeout也不会执行回调)

所以总结执行顺序为:

同步任务 (调用栈清空)=> 微任务 => DOM渲染(比如说添加几个标签) => 宏任务

宏任务微任务的嵌套:

在执行宏任务的过程中,创建了一个微任务。但是需要先把当前这个宏任务执行完,再去创建并执行微任务。

参考视频链接:

  1. Event loop 事件轮询以及微任务和宏任务
  2. JavaScript 宏任务与微任务 - Web前端工程师面试题讲解