详细聊聊React源码中的位运算技巧

 更新时间:2021年10月12日 11:40:26   作者:魔术师卡颂  
众所周知在React中,主要用到3种位运算符 —— 按位与、按位或、按位非,下面这篇文章主要给大家介绍了关于React源码中的位运算技巧的相关资料,需要的朋友可以参考下

前言

这两年有不少朋友和我吐槽React源码,比如:

  • 调度器为什么用小顶堆这种数据结构,直接用数组不行?
  • 源码里各种单向链表、环状链表,直接用数组不行?
  • 源码里各种位运算,有必要么?

作为业务依赖的框架,为了提升一点点运行时性能,React从不吝惜将源码写的很复杂。

在涉及状态、标记位、优先级操作的地方大量使用了位运算。
本文会讲解其中比较有代表性的部分。学到之后,当遇到类似场景时露一手,你就是业务线最靓的仔。

几个常用位运算

在JS中,位运算的操作数会先转换为Int32(32位有符号整型),执行完位运算会Int32对应浮点数。

在React中,主要用到3种位运算符 —— 按位与、按位或、按位非。

按位与(&)

对于两个二进制操作数的每个bit,如果都为1,则结果为1,否则为0。

举个例子,计算3 & 2,首先将操作数转化为Int32:

// 3对应的 Int32
0b000 0000 0000 0000 0000 0000 0000 0011 
// 2对应的 Int32
0b000 0000 0000 0000 0000 0000 0000 0010 

为了直观,我们排除前面的0,只保留最后8位(实际参与计算的应该是32位):

  0000 0011
& 0000 0010
-----------
  0000 0010

所以3 & 2计算结果转化为浮点数后为2。

按位或(|)

对于两个二进制操作数的每个bit,如果都为0,则结果为0,否则为1。

计算10 | 3:

  0000 1010
| 0000 0011
-----------
  0000 1011

计算结果转化为浮点数后为11。

按位非(~)

对一个二进制操作数的每个bit,逐位进行取反操作(0、1互换)

对于~3,将3转化为Int32后逐位取反:

// 3对应的 Int32
0b000 0000 0000 0000 0000 0000 0000 0011 
// 逐位取反
0b111 1111 1111 1111 1111 1111 1111 1100

计算结果转化为浮点数后为-4。

如果你对这个结果有疑惑,可以去了解补码相关知识

让我们从易到难,看看位运算在React中的应用。

标记状态

React源码内部有多个上下文环境,在执行函数时经常需要判断当前处在哪个上下文环境中。

假设共有三种上下文情况:

// A上下文
const A = 1;
// B上下文
const B = 2;
// 没有处在上下文
const NoContext = 0;

当进入某个上下文时,可以使用按位或操作标记进入:

// 当前所处上下文
let curContext = 0;

// 进入A上下文
curContext |= A;

我们用8位二进制举例(同样,实际应该是Int32,这里是为了简化),curContext与A执行按位或操作:

  0000 0000  // curContext
| 0000 0001  // A
-----------
  0000 0001

此时可以结合按位与操作与NoContext来判断是否处在某一上下文中:

// 是否处在A上下文中 true
(curContext & A) !== NoContext

// 是否处在B上下文中 false
(curContext & B) !== NoContext

离开某上下文后,结合按位与、按位非移除标记:

// 从当前上下文中移除上下文A
curContext &= ~A;

// 是否处在A上下文中 false
(curContext & A) !== NoContext

curContext与~A执行按位与操作:

  0000 0001  // curContext
& 1111 1110  // ~A
-----------
  0000 0000

即从curContext中移除A。

当业务中需要同时处理多个状态时,可以使用如上位运算技巧。

优先级计算

在React中,不同情况下调用this.setState触发的更新会拥有不同优先级。优先级之间的比较、挑选同样使用了位运算。
具体来说,React中用31个bit位保存更新(之所以是31而不是32是因为Int32的最高位是符号位,不保存具体的数)。

处在越低bit位的更新优先级越高(越需要优先处理)。

举个例子,假设当前应用存在2个更新:

0b000 0000 0000 0000 0000 0000 0001 0001

其中第1位的更新优先级最高(需要同步处理),第5位为默认优先级。

React经常需要找出当前最高优先级的更新在哪一位(如上例子中在第一位),方法如下:

function getHighestPriorityLane(lanes) {
  return lanes & -lanes;
}

解释下,由于Int32采用补码表示,所以-lanes可以看作如下两步操作:

  1. lanes取反(~lanes)
  2. 加1

为了直观,用8位表示:

lanes  0001 0001
~lanes 1110 1110 // 第一步
+1     1110 1111 // 第二步

则lanes & -lanes如下:

  0001 0001 // lanes  
& 1110 1111 // -lanes
-----------
  0000 0001

取到的就是第一位(已有更新中最高的优先级)。

总结

虽然业务中不常使用位操作,但在特定场景下位操作时很方便、高效的方式。

这波操作你爱了么?

到此这篇关于React源码中位运算技巧的文章就介绍到这了,更多相关React源码中位运算技巧内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解React 条件渲染

    详解React 条件渲染

    这篇文章主要介绍了React 条件渲染的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • react diff 算法实现思路及原理解析

    react diff 算法实现思路及原理解析

    这篇文章主要介绍了react diff 算法实现思路及原理解析,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有我们常见的 key 的作用,需要的朋友可以参考下
    2022-05-05
  • React 高阶组件入门介绍

    React 高阶组件入门介绍

    本篇文章主要介绍了React高阶组件入门介绍,这篇文章中我们详细的介绍了什么是高阶组件,如何使用高阶组件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • React之echarts-for-react源码解读

    React之echarts-for-react源码解读

    这篇文章主要介绍了React之echarts-for-react源码解读,echarts-for-react的源码非常精简,本文将针对主要逻辑分析介绍,需要的朋友可以参考下
    2022-10-10
  • nodejs和react实现即时通讯简易聊天室功能

    nodejs和react实现即时通讯简易聊天室功能

    这篇文章主要介绍了nodejs和react实现即时通讯简易聊天室功能,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • Vite + React从零开始搭建一个开源组件库

    Vite + React从零开始搭建一个开源组件库

    这篇文章主要介绍了Vite + React 如何从0到1搭建一个开源组件库,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • 浅谈React 服务器端渲染的使用

    浅谈React 服务器端渲染的使用

    本篇文章主要介绍了浅谈React 服务器端渲染的使用,React是最受欢迎的客户端 JavaScript 框架,在本教程中,我们将逐步向您介绍服务器端的渲染示例
    2018-05-05
  • React路由拦截模式及withRouter示例详解

    React路由拦截模式及withRouter示例详解

    这篇文章主要为大家介绍了React路由拦截模式及withRouter示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 教你使用vscode 搭建react-native开发环境

    教你使用vscode 搭建react-native开发环境

    本文记录如何使用vscode打造一个现代化的react-native开发环境,旨在提高开发效率和质量。本文给大家分享我遇到的问题及解决方法,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • ReactDOM 隐藏特性详解

    ReactDOM 隐藏特性详解

    这篇文章主要为大家介绍了ReactDOM 隐藏特性详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09

最新评论