成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

React 中,用到的幾種淺比較方式及其比較成本科普

開(kāi)發(fā) 前端
這篇文章主要給大家介紹幾種 React 在 Diff 過(guò)程中用到的比較方式,以及當(dāng)這幾種方式大量執(zhí)行時(shí),執(zhí)行所要花費(fèi)的時(shí)間。

開(kāi)發(fā)中的絕大多數(shù)時(shí)候,我們并不需要關(guān)注 React 項(xiàng)目的性能問(wèn)題。雖然我們?cè)谇懊鎺讉€(gè)章節(jié)中,也花了幾篇文章來(lái)分析如何優(yōu)化 React 的性能體驗(yàn),但是這些知識(shí)點(diǎn)在開(kāi)發(fā)過(guò)程中能用到的機(jī)會(huì)其實(shí)比較少。面試的時(shí)候用得比較多。

但是,當(dāng)你的項(xiàng)目遇到性能瓶頸,如何優(yōu)化性能就變得非常重要。當(dāng)然,我們前面幾篇文章已經(jīng)把性能優(yōu)化的方式和方法說(shuō)得非常清晰了,大家可以回顧一下。這篇文章我們要分享的重點(diǎn)是,當(dāng)我采用不同的方式優(yōu)化之后,代碼邏輯執(zhí)行所要付出的代價(jià)到底如何。

例如,當(dāng)我們得知 React 的 DIFF 是全量比較的時(shí)候,可能第一個(gè)反應(yīng)就是覺(jué)得他性能差。但是具體性能差到什么程度呢?有沒(méi)有一個(gè)具體的數(shù)據(jù)來(lái)支撐?不確定,這只是一種主觀感受。優(yōu)化之后的性能到底強(qiáng)不強(qiáng)呢,也不敢肯定。

因此,這篇文章主要給大家介紹幾種 react 在 diff 過(guò)程中用到的比較方式,以及當(dāng)這幾種方式大量執(zhí)行時(shí),執(zhí)行所要花費(fèi)的時(shí)間。

一、對(duì)象直接比較

又稱(chēng)為全等比較,這是一種成本最低的比較方式。在 React 中,state 與 props 的比較都會(huì)用到這樣的方式。

var prevProps = {}
var nextProps = {}

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

那么,這種比較方式的成本有多低呢?我們來(lái)寫(xiě)一個(gè)循環(huán)簡(jiǎn)單驗(yàn)證一下。分別看看比較一萬(wàn)次需要多長(zhǎng)時(shí)間。

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)

執(zhí)行結(jié)果會(huì)有小范圍波動(dòng),展示出來(lái)的結(jié)果都是取的多次執(zhí)行的平均值,或者出現(xiàn)次數(shù)最多的執(zhí)行結(jié)果。比如本案例執(zhí)行,用時(shí)最短的是 0.3 ms,用時(shí)最長(zhǎng)的是 0.8 ms。

可以看到,對(duì)比一萬(wàn)次,用時(shí)約  0.6ms。

對(duì)比一百萬(wàn)次,用時(shí)約 6.4ms。

通常情況下,我們項(xiàng)目的規(guī)模應(yīng)該很難超過(guò)一萬(wàn)次,控制得好一點(diǎn),一般都在 1000 次以?xún)?nèi)。多一點(diǎn)也應(yīng)該在 5000 次以?xún)?nèi),5000 次用這種方式的對(duì)比只需要 0.3ms 左右。

二、Object.is

Object.is 是一種與全等比較相似但不同的比較方式,他們的區(qū)別就在于處理帶符號(hào)的 0 和 NaN 時(shí)結(jié)果不一樣。

+0 === -0 // true
Object.is(+0, -0) // false

NaN === NaN // false
Object.is(NaN, NaN) // true

React 源碼里為 Object.is 做了兼容處理,因此多了一點(diǎn)判斷,所以他的性能上會(huì)比全等要差一些。

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;

那么差多少呢?我們先寫(xiě)一個(gè)邏輯來(lái)看一下執(zhí)行一萬(wàn)次比較需要多久。

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)

執(zhí)行結(jié)果如下,大概是 0.8ms。

執(zhí)行一百萬(wàn)次,用時(shí)約 11.4ms。

那么我們的項(xiàng)目規(guī)模在 5000 次比較以?xún)?nèi)的話(huà),用時(shí)估計(jì)在 0.4ms 左右,比全等比較多用了 0.1ms。

三、shallowEqual

這種淺比較的成本就稍微大一些,例如,當(dāng)我們對(duì)子組件使用了 memo 包裹之后,那么在 diff 過(guò)程中,對(duì)于 props 的比較方式就會(huì)轉(zhuǎn)變成這樣方式,他們會(huì)遍歷判斷 props 第一層每一項(xiàng)子屬性是否相等。

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 中出現(xiàn)的次數(shù)非常的少,只有我們手動(dòng)新增了 memo 之后才會(huì)進(jìn)行這種比較,因此,我們測(cè)試的時(shí)候,先以 1000 次為例看看結(jié)果。

我們定義兩個(gè)數(shù)量稍微多一點(diǎn)的 props 對(duì)象,他們最有最后一項(xiàng)不相同,因此比較的次數(shù)會(huì)拉滿(mǎn)。

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}

完整代碼如下:

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 次比較結(jié)果耗時(shí)如下,約為 1.4ms。

5000 次比較結(jié)果耗時(shí)如下,約為 3.6ms。

10000 次比較結(jié)果耗時(shí)如下,約為 6.6 ms。

這里我們可以做一個(gè)簡(jiǎn)單的調(diào)整,讓對(duì)比耗時(shí)直接少一半。那就是把唯一的變化量,寫(xiě)到前面來(lái),如圖所示,耗時(shí)只用了 3.1ms。

運(yùn)用到實(shí)踐中,就是把 props 中的變量屬性,盡量寫(xiě)在前面,能夠大幅度提高對(duì)比性能。

四、總結(jié)

次數(shù)

全等

is

shallow

五千

0.3

0.4

3.6

一萬(wàn)

0.6

0.8

6.6

百萬(wàn)

6.4

11.4

162

因此我們從測(cè)試結(jié)果中看到,全量 diff 并不可怕,如果你對(duì)性能優(yōu)化的理解非常到位,那么能你的項(xiàng)目中,全量 diff 所花費(fèi)的時(shí)間只有 0.幾ms,理論的極限性能就是只在你更新的組件里對(duì)比出差異,執(zhí)行 re-render。

當(dāng)然,由于對(duì)于 React 內(nèi)部機(jī)制的理解程度不同,會(huì)導(dǎo)致一些差異,例如有些同學(xué)的項(xiàng)目中,會(huì)執(zhí)行過(guò)多的冗余 re-render。從而導(dǎo)致在大型項(xiàng)目中性能體驗(yàn)可能出現(xiàn)問(wèn)題。那么這種情況下,也不用擔(dān)心,有一種超級(jí)笨辦法,那就是在項(xiàng)目中,結(jié)合我們剛才在 shallowEqual 中提高的優(yōu)化方案,無(wú)腦使用 useCallback 與 memo,你的項(xiàng)目性能就能得到明顯的提高,當(dāng)然,這個(gè)方案不夠優(yōu)雅但是管用。

可以看出,React 性能優(yōu)化最重要的手段非常簡(jiǎn)單:就是控制當(dāng)前渲染內(nèi)容的節(jié)點(diǎn)規(guī)模。

責(zé)任編輯:姜華 來(lái)源: 這波能反殺
相關(guān)推薦

2022-04-14 09:01:39

React源碼Flow

2011-04-08 15:19:04

開(kāi)發(fā)工具開(kāi)發(fā)

2019-07-31 07:36:27

無(wú)線技術(shù)工業(yè)物聯(lián)網(wǎng)IIOT

2018-05-23 09:15:54

存儲(chǔ)接口協(xié)議

2010-06-24 16:42:30

視頻監(jiān)控

2023-05-07 07:56:53

Python方式

2022-11-03 15:22:15

數(shù)據(jù)結(jié)構(gòu)Python

2022-02-14 13:58:32

操作系統(tǒng)JSON格式鴻蒙

2011-09-22 13:49:44

XML基準(zhǔn)測(cè)試

2014-05-29 11:09:52

無(wú)線通信技術(shù)

2011-03-18 10:25:20

javac++Python

2011-04-08 15:58:02

開(kāi)發(fā)工具開(kāi)發(fā)

2015-12-16 13:48:14

云成本云計(jì)算

2009-10-26 13:16:46

2023-03-07 16:12:32

2010-09-14 12:19:02

2009-07-23 09:25:28

SaaS成本

2016-11-14 09:42:58

公共云私有云成本

2019-08-29 09:00:55

開(kāi)發(fā)Flutter框架

2019-12-16 08:00:00

ReactAngularVue
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 黄色在线观看国产 | 久久久免费观看视频 | 桃色五月 | 91久久国产综合久久 | 国产一区二 | 亚洲国产电影 | 国产一区二区三区久久 | 国产日韩欧美精品一区二区三区 | 欧美精品被 | 欧美视频福利 | 91视频a | 久久精品国产亚洲a | 天堂网中文字幕在线观看 | 亚洲人的av| 国产日韩免费观看 | 亚洲精品久久久蜜桃 | 久久国产精品一区二区三区 | 免费中文字幕 | 国产国产精品久久久久 | 激情一区二区三区 | 一本大道久久a久久精二百 国产成人免费在线 | 欧美一级小视频 | 中文字幕成人免费视频 | 欧美激情精品久久久久久变态 | 97人澡人人添人人爽欧美 | 国产精品欧美精品日韩精品 | 国产人免费人成免费视频 | 国产精品久久久久久婷婷天堂 | 色综合久久久 | 国产精品久久久久久久久久久久 | 别c我啊嗯国产av一毛片 | 青青草精品 | 亚洲电影第三页 | 91色在线| 久久国产精品免费视频 | 综合色久 | 成人精品国产免费网站 | 男女爱爱福利视频 | 翔田千里一区二区 | 亚洲国产成人精品女人久久久 | 91国产在线播放 |