js

js 事件循环

js 是单线程语言,事件循环是为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程阻塞

主线程

一些具有回调函数的事件将进入执行栈中,等待主线程读取,等待主线程读取,遵循先进先出原则。主线程循环:即主线程会不停的从执行栈中读取事件,会执行完所有栈中的同步代码。当遇到一个异步事件后,并不会一直等待异步事件返回结果,而是会将这个事件挂在与执行栈不同的队列中,我们称之为任务队列(Task Queue)。当主线程将执行栈中所有的代码执行完之后,主线程将会去查看任务队列是否有任务。如果有,那么主线程会依次执行那些任务队列中的回调函数。

宏任务与微任务

异步任务分为 宏任务(macrotask) 与 微任务 (microtask)

  1. 宏任务(macrotask): script(整体代码)、setTimeout、setInterval、UI 渲染、 I/O、postMessage、 MessageChannel、setImmediate(Node.js 环境)

  2. 微任务(microtask): Promise、 MutaionObserver、process.nextTick(Node.js 环境)

Event Loop(事件循环)

  1. 执行栈选择最先进入队列的宏任务

  2. 然后执行微任务

  3. ...循环执行完全部任务(宏任务-微任务-宏任务)

数据类型

值类型(基本类型)

字符串(string)、数值(number)、布尔值(boolean)、undefined、空值(null)、symbol

引用类型

对象(Object)、数组(Array)、函数(Function)

diff 算法

计算出 Virtual DOM 中真正变化的部分,并只针对该部分进行原生 DOM 操作,而非重新渲染整个页面

tree diff

两棵树只对同一层级节点进行比较,只要该节点不存在了,那么该节点与其所有子节点会被完全删除,不在进行进一步比较

只需要遍历一次,便完成对整个 DOM 树的比较

component diff

同类型组件,组件 A 转化为了组件 B,如果 virtual DOM 无变化,可以通过 shouldComponentUpdate()方法优化

不同类型的组件,那么 diff 算法会把要改变的组件判断为 dirty component,从而替换整个组件的所有节点

element diff

key 往前移动的节点不进行任何操作,所以当把最后一个节点移动到头部时,性能损耗最大

  • 插入: 新的组件不在原来的集合中,而是全新的节点,则对集合进行插入操作

  • 删除: 组件已经在集合中,但集合已经更新,此时节点就需要删除

  • 移动: 组件已经存在于集合中,并且集合更新时,组件并没有发生更新,只是位置发生改变(同一层的节点添加唯一 key 进行区分,并且移动,当新集合中位置在旧集合之后时,需要移动)

原型链

事件

事件流

  1. 事件捕获阶段

  2. 目标阶段

  3. 事件冒泡阶段

事件冒泡

由内向外进行事件传播,直到根结点

事件捕获

从根结点开始,由外向内进行事件传播,直到目标元素

事件代理

利用事件冒泡的原理,将事件处理器添加到父元素,等待子元素事件冒泡,通过target属性能区分子元素,从而对不同子元素做不同处理

减少了事件处理器,节省内存

模块化

ES6 module

commonjs

V8垃圾回收机制

Last updated