返回顶部
首页 > 资讯 > 前端开发 > JavaScript >浅谈React中的浅比较是如何工作的
  • 957
分享到

浅谈React中的浅比较是如何工作的

2024-04-02 19:04:59 957人浏览 薄情痞子
摘要

React 中浅比较的概念无处不在,它在不同的流程中起着关键的作用,也可以在React组件的多个生命周期中找到。比如,React Hooks中的依赖数组,通过React.memo进行

React 中浅比较的概念无处不在,它在不同的流程中起着关键的作用,也可以在React组件的多个生命周期中找到。比如,React Hooks中的依赖数组,通过React.memo进行记忆。在React的官方文档中也多次提到“浅比较”这个概念,下面我们就来看看React中的浅比较是如何工作的!

想要理解浅比较的概念,最直接的方法就是研究React的源代码,下面就来看看React中的shallowEqual.js 文件:

import is from './objectIs';
import hasOwnProperty from './hasOwnProperty';


function shallowEqual(objA: mixed, objB: mixed): boolean {
  if (is(objA, objB)) {
    return true;
  }

  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false;
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }
  
  // Test for A's keys different from B.
  for (let i = 0; i < keysA.length; i++) {
    const currenTKEy = keysA[i];
    if (
      !hasOwnProperty.call(objB, currentKey) ||
      !is(objA[currentKey], objB[currentKey])
    ) {
      return false;
    }
  }

  return true;
}

这里执行了很多步操作,下面就来将其拆分并逐步执行这些功能。先来看看函数的定义,这个函数接受两个需要比较的对象,这里的代码使用 Flow 作为类型检查系统。两个函数参数都是使用特殊的混合 Flow 类型定义,类似于 typescript 的 unknown,它表明函数可以是任何类型的值。

function shallowEqual(objA: mixed, objB: mixed): boolean {
    // ...
}

之后使用 React 内部对象的 is 函数将两个函数参数进行比较。导入的 is 函数只不过是javascript 的 Object.is 函数的polyfill 版本。 这个比较函数基本上等同于常见的 === 运算符,但有两个例外:

  • Object.is 认为 +0 和 -0 不相等,而 === 认为它们相等;
  • Object.is 认为 Number.NaN 和 NaN 相等,而 === 认为它们不相等。

基本上,第一个条件语句可以处理所有简单的情况:如果两个函数参数具有相同的值,对于原始类型,或引用相同的对象(数组和对象),那么通过浅比较认为它们相等的。

import is from './objectIs';

function shallowEqual(objA: mixed, objB: mixed): boolean {
  if (is(objA, objB)) {
    return true;
  }
    // ...
}

在处理两个函数参数值相等或者引用同一个对象的所有简单情况之后,来看看更复杂的结构:数组和对象。
为了确保现在要处理的是两个复杂的结构,代码会检查任一参数是不是object类型或者等于null,前者用来确保我们处理的数组或对象,后者用来过滤掉空值,因为typeof null的结果也是 object。如果任何一个条件成立,那两个参数一定是不相等的(否则前面的条件语句就会将它们过滤掉),因此浅比较直接返回false。

function shallowEqual(objA: mixed, objB: mixed): boolean {
    // ...

  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false;
  }

    // ...
}

现在就可以确保我们处理的是数组和对象了,接下来我们深入研究复杂数据结构的值,并在两个函数参数之间进行比较。在此之前,先来检查两个参数中值的数量是否相等,如果不相等,直接就可以确定两个值是不相等的。对于对象,得到的keys数组就是由实际的key组成的;对于数组,得到keys数组数是由字符串类型的数组索引组成的。

function shallowEqual(objA: mixed, objB: mixed): boolean {
    // ...

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

    // ...
}

最后一步,按照 key 来迭代两个函数参数的值,并逐个验证他们是否是相等的。为此,代码使用到了上一步中生成的keys数组,使用 hasOwnProperty 检查key是否实际上是参数的属性,并使用 Object.is 函数进行比较。

import hasOwnProperty from './hasOwnProperty';

function shallowEqual(objA: mixed, objB: mixed): boolean {
    // ...

  // Test for A's keys different from B.
  for (let i = 0; i < keysA.length; i++) {
    const currentKey = keysA[i];
    if (
      !hasOwnProperty.call(objB, currentKey) ||
      !is(objA[currentKey], objB[currentKey])
    ) {
      return false;
    }
  }

  return true;
}

如果任何两个key对应的值是不相等的,那两个对象肯定就是不相等的,因此直接人会false,结束循环。如果所有的值都是相等的,就返回 true。

至此,我们通过 React 源码学习了 React 中的浅比较,下面来总结一下其中有趣的知识吧:

  • 浅比较使用的是 Object.is 函数,而不是使用严格相等 === 运算符;
  • 通过浅比较,空对象和空数组是等价的;
  • 通过浅比较,以数组索引为 key 和数组值为value的对象是等价的,比如:{ 0: 2, 1: 3 } 等价于 [2, 3];
  • 由于通过Object.is比较的+0 和 -0、Number.NaN 和 NaN是不相等的,所以在复杂结构中比较时,这也是适用的;
  • 虽然{} 和 [] 钱比较是相等的,但是嵌套在对象中对象是不相等的,比如:{ someKey: {} } 和 { someKey: [] } 是不相等的。

源码:https://GitHub.com/facebook/react/blob/main/packages/shared/shallowEqual.js

到此这篇关于浅谈React 中的浅比较是如何工作的的文章就介绍到这了,更多相关React 浅比较内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 浅谈React中的浅比较是如何工作的

本文链接: https://lsjlt.com/news/147437.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 浅谈React中的浅比较是如何工作的
    React 中浅比较的概念无处不在,它在不同的流程中起着关键的作用,也可以在React组件的多个生命周期中找到。比如,React Hooks中的依赖数组,通过React.memo进行...
    99+
    2024-04-02
  • React中的浅比较是怎么工作的
    这篇文章主要介绍了React中的浅比较是怎么工作的的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇React中的浅比较是怎么工作的文章都会有所收获,下面我们一起来看看吧。想要理解浅比较的概念,最直接的方法就是研究...
    99+
    2023-06-30
  • 浅谈java对象的比较
    目录1、元素的比较2、类的比较3、比较方法3.1 重写equals方法3.2 基于Comparble接口类的比较3.3 基于比较器比较基于比较器比较:Comparator接口3.4 ...
    99+
    2024-04-02
  • 浅谈java中HashMap键的比较方式
    先看一个例子 Integer integer=12344; Integer integer1=12344; 在Java中Integer 和Integer1是不相等的,但是...
    99+
    2024-04-02
  • 浅谈Springrefresh的工作流程
    目录功能分类具体步骤1. prepareRefresh2. obtainFreshBeanFactory3. prepareBeanFactory4. postProcessBean...
    99+
    2023-05-17
    Spring refresh refresh工作流程
  • 浅谈Android中AsyncTask的工作原理
    目录概述AsyncTask使用方法AsyncTask的4个核心方法AsyncTask的工作原理概述 实际上,AsyncTask内部是封装了Thread和Handler。虽然Async...
    99+
    2024-04-02
  • 浅谈Java字符串比较的三种方法
    目录java字符串如何进行比较?1.通过使用 equals() 方法2.通过使用 == 运算符3.通过使用 compareTo() 方法java字符串如何进行比较? 我们可以根据内容...
    99+
    2023-05-14
    Java字符串 Java字符串比较
  • 浅谈java自定义中类两个对象的比较
    目录 实现比较两个对象是否相同 1.前置代码 1.学生类 2.示例  3.输出  4.原因 2.那么我们要怎么做呢 1.对Student类中重新实现quals方法(即对equals方法重写)  2.完整代码如下: 3.具体操作 4.演示 ...
    99+
    2023-09-20
    java 开发语言 学习 学习方法 程序人生 intellij-idea
  • 浅谈Vue3中key的作用和工作原理
    这个key属性有什么作用呢?我们先来看一下官方的解释: kekey属性主要用在Vue的虚拟DOM diff算法中,在新旧nodes对比时辨识Vnodes; 如果不使...
    99+
    2024-04-02
  • 详解React中Props的浅对比
    目录类组件的Props对比 shallowEqual 浅对比函数组件的浅对比 上一周去面试的时候,面试官我PureComponent里是如何对比props的,概念已经牢记脑中,脱口而...
    99+
    2024-04-02
  • 浅谈Pandas dataframe数据处理方法的速度比较
    数据修改主要以增删改差为主,这里比较几种写法在数据处理时间上的巨大差别。 数据量大概是500万行级别的数据,文件大小为100M。 1.iloc iloc是一种速度极其慢的写法。这里我...
    99+
    2024-04-02
  • 如何浅谈MySQL中的group by
    今天就跟大家聊聊有关如何浅谈MySQL中的group by,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1、前言MySQL的group by用于对查询的数据进行分组;此外MySQL提...
    99+
    2023-06-25
  • 浅谈Webpack是如何打包CommonJS的
    目录一、书写代码二、使用webpack打包编译三、解析CommonJS 是 Node 中的一种模块化规范,其是一种运行在 Node 环境下的代码,这种代码是不能直接运行到浏览器环境中...
    99+
    2024-04-02
  • 在Java中如何比较两个对象浅析
    Common Lang 中的 Builder 包内提供了一个 DiffBuilder 类,可以比较两个对象,并返回不同的部分。 首先在要比较对象的类中实现 Diffable...
    99+
    2024-04-02
  • 浅谈Python中对象是如何被调用的
    目录楔子从 Python 的角度看对象的调用从解释器的角度看对象的调用小结楔子 我们知道对象是如何被创建的,主要有两种方式,一种是通过Python/C API,另一种是通过调用类型对...
    99+
    2024-04-02
  • 浅谈Nodejs中的作用域问题
    在JS中有全局作用域和函数作用域,而在Nodejs中也自己的作用域,分为全局作用域(global)和模块作用域。 js作用域: 以前学js的时候我们的全局对象是window,如: var a = 10;...
    99+
    2022-06-04
    浅谈 作用 Nodejs
  • 浅谈Android IPC机制之Binder的工作机制
    目录进程和线程的关系跨进程的种类Serializable,Parcelable接口Binder进程和线程的关系 按照操作系统中的描述,线程是CPU调度的最小单位,同时线程也是一种有限...
    99+
    2024-04-02
  • React中Hooks是如何工作的
    React中Hooks是如何工作的?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1. React Hooks VS 纯函数React Hook 说白了就是 Re...
    99+
    2023-06-15
  • 浅谈一段java代码是如何执行的
    目录1. 编译成class2. jvm的构成3. 方法的顺序执行和栈帧4. class文件反编译过后的样子5. 指令集详解本文分享自华为云社区《一段java代码是如何执行的》,原文作...
    99+
    2024-04-02
  • 浅谈Android app开发中Fragment的Transaction操作
    在Android中,对Fragment的操作都是通过FragmentTransaction来执行。而从Fragment的结果来看,FragmentTransaction中对Fr...
    99+
    2022-06-06
    fragment app Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作