1. React中的链表
React Fiber版本的源码中使用到链表的数据结构(为了实现低优先级任务的暂停与重启),包括单向链表和环状链表。
- 首先,Hooks是以单向链表的形式存储在 Fiber 的 memoizedState 属性身上
- 同时,每个hooks又拥有自己的更新队列queue,queue.pending 会指向一个环状链表
2. 单向链表代码实现
function buildQueue(queue,action){
const update = {action,next:null}
const pending = queue.pending
if(!pending){
queue.pending = update
}else{
let current = queue.pending
// 找到末尾的元素
while(current.next){
current = current.next
}
// 将update挂载到链表的末尾
current.next = update
}
}
// excute
let queue = {pending:null}
buildQueue(queue,'hooks1')
buildQueue(queue,'hooks2')
// output: queue.pending = {action:'hooks1',next:{action:'hooks2',next:null}}
3. 环状链表代码实现
function dispatchAction(queue,action){
const update = {action,next:null}
const pending = queue.pending
if(pending === null){
update.next = update // 自己与自己创建一个环状链表
}else{
update.next = pending.next
pending.next = update
}
queue.pending = update
}
let queue = {pending:null}
/**
* update.next === update
* queue.pending === update(action)
*/
dispatchAction(queue,'action')
/**
* update(action1).next -> update(action).next [update(action)]
* update1 的next 指向 update
* queue.pending.next [update(update)] -> update(action1)
* update 指向 update1
* queue.pending -> update(action1)
* queue.pending 指向 update1
*/
dispatchAction(queue,'action1')
- 由图可知,queue.pending 永远指向最后一个更新
-
由图可知,pending.next 永远指向第一个更新
4. 结语
栈,堆,队列,链表,树等数据结构我们平时写代码也许体会不到用处,但在学习框架源码的时候,我们可以体会到数据结构的妙处(虚拟dom与diff算法是对二叉树的应用与遍历,hooks的更新队列是循环链表),加深我们对数据的理解,提升我们的逻辑思维。