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

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

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

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

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

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

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

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

一、对象直接比较

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

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

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

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

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

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

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

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

二、Object.is

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

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

React 源码里为 Object.is 做了兼容处理,因此多了一点判断,所以他的性能上会比全等要差一些。eqr28资讯网——每日最新资讯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;

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

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

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

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

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

三、shallowEqual

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

我们定义两个数量稍微多一点的 props 对象,他们最有最后一项不相同,因此比较的次数会拉满。eqr28资讯网——每日最新资讯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}

完整代码如下:eqr28资讯网——每日最新资讯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。eqr28资讯网——每日最新资讯28at.com

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

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

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

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

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

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

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

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

四、总结

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

标签:
  • 热门焦点
  • 一加Ace2 Pro真机揭晓 钛空灰配色质感拉满

    终于,在经过了几波预热之后,一加Ace2 Pro的外观真机图在网上出现了。还是博主数码闲聊站曝光的,这次的外观设计还是延续了一加11的方案,只是细节上有了调整,例如新加入了钛空灰
  • 石头智能洗地机A10 Plus体验:双向自清洁治好了我的懒癌

    一、前言和介绍专为家庭请假懒人而生的石头科技在近日又带来了自己的全新旗舰新品,石头智能洗地机A10 Plus。从这个产品名上就不难看出,这次石头推出的并不是常见的扫地机器
  • 6月iOS设备好评榜:第一蝉联榜首近一年

    作为安兔兔各种榜单里变化最小的那个,2023年6月的iOS好评榜和上个月相比没有任何排名上的变化,仅仅是部分设备好评率的下降,长年累月的用户评价和逐渐退出市场的老款机器让这
  • 得物效率前端微应用推进过程与思考

    一、背景效率工程随着业务的发展,组织规模的扩大,越来越多的企业开始意识到协作效率对于企业团队的重要性,甚至是决定其在某个行业竞争中突围的关键,是企业长久生存的根本。得物
  • 这款新兴工具平台,让你的电脑效率翻倍

    随着信息技术的发展,我们获取信息的渠道越来越多,但是处理信息的效率却成为一个瓶颈。于是各种工具应运而生,都在争相解决我们的工作效率问题。今天我要给大家介绍一款效率
  • 一个注解实现接口幂等,这样才优雅!

    场景码猿慢病云管理系统中其实高并发的场景不是很多,没有必要每个接口都去考虑并发高的场景,比如添加住院患者的这个接口,具体的业务代码就不贴了,业务伪代码如下:图片上述代码有
  • 中国家电海外掘金正当时|出海专题

    作者|吴南南编辑|胡展嘉运营|陈佳慧出品|零态LT(ID:LingTai_LT)2023年,出海市场战况空前,中国创业者在海外纷纷摩拳擦掌,以期能够把中国的商业模式、创业理念、战略打法输出海外,他们依
  • 苹果、三星、惠普等暂停向印度出口笔记本和平板电脑

    集微网消息,据彭博社报道,在8月3日印度突然禁止在没有许可证的情况下向印度进口电脑/平板及显示器等产品后,苹果、三星电子和惠普等大公司暂停向印度
  • Counterpoint :OPPO双旗舰战略全面落地 高端产品销量增长22%

    2023年6月30日,全球行业分析机构Counterpoint Research发布的《中国智能手机高端市场白皮书》显示,中国智能手机品牌正在寻求高质量发展,中国高端智能
Top