溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

React中的淺比較是怎么工作的

發(fā)布時(shí)間:2022-04-27 08:49:15 來(lái)源:億速云 閱讀:217 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹了React中的淺比較是怎么工作的的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇React中的淺比較是怎么工作的文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。

想要理解淺比較的概念,最直接的方法就是研究React的源代碼,下面就來(lái)看看React中的shallowEqual.js 文件:

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

/**
 * Performs equality by iterating through keys on an object and returning false
 * when any key has values which are not strictly equal between the arguments.
 * Returns true when the values of all keys are strictly equal.
 */
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;
}

這里執(zhí)行了很多步操作,下面就來(lái)將其拆分并逐步執(zhí)行這些功能。先來(lái)看看函數(shù)的定義,這個(gè)函數(shù)接受兩個(gè)需要比較的對(duì)象,這里的代碼使用 Flow 作為類(lèi)型檢查系統(tǒng)。兩個(gè)函數(shù)參數(shù)都是使用特殊的混合 Flow 類(lèi)型定義,類(lèi)似于 TypeScript 的 unknown,它表明函數(shù)可以是任何類(lèi)型的值。

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

之后使用 React 內(nèi)部對(duì)象的 is 函數(shù)將兩個(gè)函數(shù)參數(shù)進(jìn)行比較。導(dǎo)入的 is 函數(shù)只不過(guò)是JavaScript 的 Object.is 函數(shù)的polyfill 版本。 這個(gè)比較函數(shù)基本上等同于常見(jiàn)的 === 運(yùn)算符,但有兩個(gè)例外:

  • Object.is 認(rèn)為 +0 和 -0 不相等,而 === 認(rèn)為它們相等;

  • Object.is 認(rèn)為 Number.NaN 和 NaN 相等,而 === 認(rèn)為它們不相等。

基本上,第一個(gè)條件語(yǔ)句可以處理所有簡(jiǎn)單的情況:如果兩個(gè)函數(shù)參數(shù)具有相同的值,對(duì)于原始類(lèi)型,或引用相同的對(duì)象(數(shù)組和對(duì)象),那么通過(guò)淺比較認(rèn)為它們相等的。

import is from './objectIs';

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

在處理兩個(gè)函數(shù)參數(shù)值相等或者引用同一個(gè)對(duì)象的所有簡(jiǎn)單情況之后,來(lái)看看更復(fù)雜的結(jié)構(gòu):數(shù)組和對(duì)象。
為了確?,F(xiàn)在要處理的是兩個(gè)復(fù)雜的結(jié)構(gòu),代碼會(huì)檢查任一參數(shù)是不是object類(lèi)型或者等于null,前者用來(lái)確保我們處理的數(shù)組或?qū)ο?,后者用?lái)過(guò)濾掉空值,因?yàn)閠ypeof null的結(jié)果也是 object。如果任何一個(gè)條件成立,那兩個(gè)參數(shù)一定是不相等的(否則前面的條件語(yǔ)句就會(huì)將它們過(guò)濾掉),因此淺比較直接返回false。

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

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

    // ...
}

現(xiàn)在就可以確保我們處理的是數(shù)組和對(duì)象了,接下來(lái)我們深入研究復(fù)雜數(shù)據(jù)結(jié)構(gòu)的值,并在兩個(gè)函數(shù)參數(shù)之間進(jìn)行比較。在此之前,先來(lái)檢查兩個(gè)參數(shù)中值的數(shù)量是否相等,如果不相等,直接就可以確定兩個(gè)值是不相等的。對(duì)于對(duì)象,得到的keys數(shù)組就是由實(shí)際的key組成的;對(duì)于數(shù)組,得到keys數(shù)組數(shù)是由字符串類(lèi)型的數(shù)組索引組成的。

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 來(lái)迭代兩個(gè)函數(shù)參數(shù)的值,并逐個(gè)驗(yàn)證他們是否是相等的。為此,代碼使用到了上一步中生成的keys數(shù)組,使用 hasOwnProperty 檢查key是否實(shí)際上是參數(shù)的屬性,并使用 Object.is 函數(shù)進(jìn)行比較。

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

如果任何兩個(gè)key對(duì)應(yīng)的值是不相等的,那兩個(gè)對(duì)象肯定就是不相等的,因此直接人會(huì)false,結(jié)束循環(huán)。如果所有的值都是相等的,就返回 true。

至此,我們通過(guò) React 源碼學(xué)習(xí)了 React 中的淺比較,下面來(lái)總結(jié)一下其中有趣的知識(shí)吧:

  • 淺比較使用的是 Object.is 函數(shù),而不是使用嚴(yán)格相等 === 運(yùn)算符;

  • 通過(guò)淺比較,空對(duì)象和空數(shù)組是等價(jià)的;

  • 通過(guò)淺比較,以數(shù)組索引為 key 和數(shù)組值為value的對(duì)象是等價(jià)的,比如:{ 0: 2, 1: 3 } 等價(jià)于 [2, 3];

  • 由于通過(guò)Object.is比較的+0 和 -0、Number.NaN 和 NaN是不相等的,所以在復(fù)雜結(jié)構(gòu)中比較時(shí),這也是適用的;

  • 雖然{} 和 [] 錢(qián)比較是相等的,但是嵌套在對(duì)象中對(duì)象是不相等的,比如:{ someKey: {} } 和 { someKey: [] } 是不相等的。

關(guān)于“React中的淺比較是怎么工作的”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“React中的淺比較是怎么工作的”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI