当前位置:首页 > 科技  > 软件

React 中,用到的几种浅比较方式及其比较成本科普

来源: 责编: 时间:2024-04-22 09:12:16 251观看
导读开发中的绝大多数时候,我们并不需要关注 React 项目的性能问题。虽然我们在前面几个章节中,也花了几篇文章来分析如何优化 React 的性能体验,但是这些知识点在开发过程中能用到的机会其实比较少。面试的时候用得比较多。

pGc28资讯网——每日最新资讯28at.com

开发中的绝大多数时候,我们并不需要关注 React 项目的性能问题。虽然我们在前面几个章节中,也花了几篇文章来分析如何优化 React 的性能体验,但是这些知识点在开发过程中能用到的机会其实比较少。面试的时候用得比较多。pGc28资讯网——每日最新资讯28at.com

但是,当你的项目遇到性能瓶颈,如何优化性能就变得非常重要。当然,我们前面几篇文章已经把性能优化的方式和方法说得非常清晰了,大家可以回顾一下。这篇文章我们要分享的重点是,当我采用不同的方式优化之后,代码逻辑执行所要付出的代价到底如何。pGc28资讯网——每日最新资讯28at.com

例如,当我们得知 React 的 DIFF 是全量比较的时候,可能第一个反应就是觉得他性能差。但是具体性能差到什么程度呢?有没有一个具体的数据来支撑?不确定,这只是一种主观感受。优化之后的性能到底强不强呢,也不敢肯定。pGc28资讯网——每日最新资讯28at.com

因此,这篇文章主要给大家介绍几种 react 在 diff 过程中用到的比较方式,以及当这几种方式大量执行时,执行所要花费的时间。pGc28资讯网——每日最新资讯28at.com

一、对象直接比较

又称为全等比较,这是一种成本最低的比较方式。在 React 中,state 与 props 的比较都会用到这样的方式。pGc28资讯网——每日最新资讯28at.com

var prevProps = {}var nextProps = {}if (prevProps === nextProps) {  ...}

那么,这种比较方式的成本有多低呢?我们来写一个循环简单验证一下。分别看看比较一万次需要多长时间。pGc28资讯网——每日最新资讯28at.com

var markTime = performance.now()var prev = {}var next = {}for(var i = 0; i <= 10000; i++) {  if (prev === next) {    console.log('相等')  }}var endTime = performance.now()console.log(endTime - markTime)

执行结果会有小范围波动,展示出来的结果都是取的多次执行的平均值,或者出现次数最多的执行结果。比如本案例执行,用时最短的是 0.3 ms,用时最长的是 0.8 ms。pGc28资讯网——每日最新资讯28at.com

可以看到,对比一万次,用时约  0.6ms。pGc28资讯网——每日最新资讯28at.com

pGc28资讯网——每日最新资讯28at.com

对比一百万次,用时约 6.4ms。pGc28资讯网——每日最新资讯28at.com

pGc28资讯网——每日最新资讯28at.com

通常情况下,我们项目的规模应该很难超过一万次,控制得好一点,一般都在 1000 次以内。多一点也应该在 5000 次以内,5000 次用这种方式的对比只需要 0.3ms 左右。pGc28资讯网——每日最新资讯28at.com

二、Object.is

Object.is 是一种与全等比较相似但不同的比较方式,他们的区别就在于处理带符号的 0 和 NaN 时结果不一样。pGc28资讯网——每日最新资讯28at.com

+0 === -0 // trueObject.is(+0, -0) // falseNaN === NaN // falseObject.is(NaN, NaN) // true

React 源码里为 Object.is 做了兼容处理,因此多了一点判断,所以他的性能上会比全等要差一些。pGc28资讯网——每日最新资讯28at.com

function is(x, y) {  return (    (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare  );}const objectIs =  typeof Object.is === 'function' ? Object.is : is;

那么差多少呢?我们先写一个逻辑来看一下执行一万次比较需要多久。pGc28资讯网——每日最新资讯28at.com

function is(x, y) {  return (    (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare  );}const objectIs =  typeof Object.is === 'function' ? Object.is : is;var markTime = performance.now()var prev = {}var next = {}for(var i = 0; i <= 10000; i++) {  if (objectIs(prev, next)) {    console.log('相等')  }}var endTime = performance.now()console.log(endTime - markTime)

执行结果如下,大概是 0.8ms。pGc28资讯网——每日最新资讯28at.com

pGc28资讯网——每日最新资讯28at.com

执行一百万次,用时约 11.4ms。pGc28资讯网——每日最新资讯28at.com

pGc28资讯网——每日最新资讯28at.com

那么我们的项目规模在 5000 次比较以内的话,用时估计在 0.4ms 左右,比全等比较多用了 0.1ms。pGc28资讯网——每日最新资讯28at.com

三、shallowEqual

这种浅比较的成本就稍微大一些,例如,当我们对子组件使用了 memo 包裹之后,那么在 diff 过程中,对于 props 的比较方式就会转变成这样方式,他们会遍历判断 props 第一层每一项子属性是否相等。pGc28资讯网——每日最新资讯28at.com

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;}

首先,这种比较方式在 React 中出现的次数非常的少,只有我们手动新增了 memo 之后才会进行这种比较,因此,我们测试的时候,先以 1000 次为例看看结果。pGc28资讯网——每日最新资讯28at.com

我们定义两个数量稍微多一点的 props 对象,他们最有最后一项不相同,因此比较的次数会拉满。pGc28资讯网——每日最新资讯28at.com

var prev = {a:1, b: 1, c: 1, d: 1, e: 1, f: 1, g: 1}var next = {a:1, b: 1, c: 1, d: 1, e: 1, f: 1, g: 2}

完整代码如下:pGc28资讯网——每日最新资讯28at.com

function is(x, y) {  return (    (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare  );}const objectIs =  typeof Object.is === 'function' ? Object.is : is;function shallowEqual(objA, objB) {  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 (      !Object.hasOwnProperty.call(objB, currentKey) ||      !is(objA[currentKey], objB[currentKey])    ) {      return false;    }  }  return true;}var markTime = performance.now()var prev = {a:1, b: 1, c: 1, d: 1, e: 1, f: 1, g: 1}var next = {a:1, b: 1, c: 1, d: 1, e: 1, f: 1, g: 2}for(var i = 0; i <= 1000; i++) {  if (shallowEqual(prev, next)) {    console.log('相等')  }}var endTime = performance.now()console.log(endTime - markTime)

1000 次比较结果耗时如下,约为 1.4ms。pGc28资讯网——每日最新资讯28at.com

pGc28资讯网——每日最新资讯28at.com

5000 次比较结果耗时如下,约为 3.6ms。pGc28资讯网——每日最新资讯28at.com

pGc28资讯网——每日最新资讯28at.com

10000 次比较结果耗时如下,约为 6.6 ms。pGc28资讯网——每日最新资讯28at.com

pGc28资讯网——每日最新资讯28at.com

这里我们可以做一个简单的调整,让对比耗时直接少一半。那就是把唯一的变化量,写到前面来,如图所示,耗时只用了 3.1ms。pGc28资讯网——每日最新资讯28at.com

pGc28资讯网——每日最新资讯28at.com

运用到实践中,就是把 props 中的变量属性,尽量写在前面,能够大幅度提高对比性能。pGc28资讯网——每日最新资讯28at.com

四、总结

次数
pGc28资讯网——每日最新资讯28at.com

全等
pGc28资讯网——每日最新资讯28at.com

is
pGc28资讯网——每日最新资讯28at.com

shallow
pGc28资讯网——每日最新资讯28at.com

五千
pGc28资讯网——每日最新资讯28at.com

0.3
pGc28资讯网——每日最新资讯28at.com

0.4
pGc28资讯网——每日最新资讯28at.com

3.6
pGc28资讯网——每日最新资讯28at.com

一万
pGc28资讯网——每日最新资讯28at.com

0.6
pGc28资讯网——每日最新资讯28at.com

0.8
pGc28资讯网——每日最新资讯28at.com

6.6
pGc28资讯网——每日最新资讯28at.com

百万
pGc28资讯网——每日最新资讯28at.com

6.4
pGc28资讯网——每日最新资讯28at.com

11.4
pGc28资讯网——每日最新资讯28at.com

162
pGc28资讯网——每日最新资讯28at.com

因此我们从测试结果中看到,全量 diff 并不可怕,如果你对性能优化的理解非常到位,那么能你的项目中,全量 diff 所花费的时间只有 0.几ms,理论的极限性能就是只在你更新的组件里对比出差异,执行 re-render。pGc28资讯网——每日最新资讯28at.com

当然,由于对于 React 内部机制的理解程度不同,会导致一些差异,例如有些同学的项目中,会执行过多的冗余 re-render。从而导致在大型项目中性能体验可能出现问题。那么这种情况下,也不用担心,有一种超级笨办法,那就是在项目中,结合我们刚才在 shallowEqual 中提高的优化方案,无脑使用 useCallback 与 memo,你的项目性能就能得到明显的提高,当然,这个方案不够优雅但是管用。pGc28资讯网——每日最新资讯28at.com

可以看出,React 性能优化最重要的手段非常简单:就是控制当前渲染内容的节点规模。pGc28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-84462-0.htmlReact 中,用到的几种浅比较方式及其比较成本科普

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 利用RSA加密打造强大License验证,确保软件正版合法运行

下一篇: 针对尺寸单位,为什么不应该使用 px 作为尺寸单位?以及最佳实践!

标签:
  • 热门焦点
  • K60 Pro官方停产 第三方瞬间涨价

    虽然没有官方宣布,但Redmi的一些高管也已经透露了,Redmi K60 Pro已经停产且不会补货,这一切都是为了即将到来的K60 Ultra铺路,属于厂家的正常操作。但有意思的是该机在停产之后
  • 在线图片编辑器,支持PSD解析、AI抠图等

    自从我上次分享一个人开发仿造稿定设计的图片编辑器到现在,不知不觉已过去一年时间了,期间我经历了裁员失业、面试找工作碰壁,寒冬下一直没有很好地履行计划.....这些就放在日
  • Python异步IO编程的进程/线程通信实现

    这篇文章再讲3种方式,同时讲4中进程间通信的方式一、 Python 中线程间通信的实现方式共享变量共享变量是多个线程可以共同访问的变量。在Python中,可以使用threading模块中的L
  • 使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 共享单车的故事讲到哪了?

    来源丨海克财经与共享充电宝相差不多,共享单车已很久没有被国内热点新闻关照到了。除了一再涨价和用户直呼用不起了。近日多家媒体再发报道称,成都、天津、郑州等地多个共享单
  • 年轻人的“职场羞耻感”,无处不在

    作者:冯晓亭 陶 淘 李 欣 张 琳 马舒叶来源:燃次元&ldquo;人在职场,应该选择什么样的着装?&rdquo;近日,在网络上,一个与着装相关的帖子引发关注,在该帖子里,一位在高级写字楼亚洲金
  • 华为HarmonyOS 4升级计划公布:首批34款机型今日开启公测

    8月4日消息,今天下午华为正式发布了HarmonyOS 4系统,在更流畅的前提下,还带来了不少新功能,UI设计也有变化,会让手机焕然一新。华为宣布,首批机型将会在
  • Windows 11发布,微软一改往常对老机型开放的态度

    距离 Windows 11 发布已经过去一周,在过去一周里,很多数码爱好者围绕其对 Android 应用的支持、对老机型的升级问题展开了激烈讨论。与以往不同的是,在这次大
  • SN570 NVMe SSD固态硬盘 价格与性能兼具

    SN570 NVMe SSD固态硬盘是西部数据发布的最新一代WD Blue系列的固态硬盘,不仅闪存技术更为精进,性能也得到了进一步的跃升。WD Blue SN570 NVMe SSD的包装外
Top