自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一道字節(jié)面試題,把群友整不會(huì)了,關(guān)于 useMemo 用法的另外一個(gè)延伸

開(kāi)發(fā) 前端
在 React 中,Hook 是基于閉包來(lái)實(shí)現(xiàn),因此幾乎每個(gè) hook 理論上都具有緩存能力。我們常用的這些 hook:useState、useRef useReducer useEffect useMemo useCallback 他們都有一些共性,那就是緩存能力。然后在語(yǔ)義上有一些差異。

群友在一次字節(jié)的面試中,被要求實(shí)現(xiàn) useToggle。

useToggle 表示兩個(gè)狀態(tài)的來(lái)回切換。

群友一想,這還不簡(jiǎn)單,于是就咔咔一頓寫,兩三筆就把該功能實(shí)現(xiàn)了。

function useToggle(value: boolean) {
  const [state, setState] = useState(value)

  const toggle = () => {
    setState(!state)
  }

  return {state, toggle}
}

搞完之后,面試官看到代碼卻說(shuō):

不太對(duì),組件重新渲染,導(dǎo)致這個(gè) hook 重新執(zhí)行了,狀態(tài)就變了。

這下直接給群友整不會(huì)了,咋回事?為什么字節(jié)面試官說(shuō)的東西跟他理解的不一樣。百思不得其解之下,在面試之后又去研究了很多方案,最后實(shí)在沒(méi)想通,又跑到群里來(lái)討論。

那么問(wèn)題來(lái)了,截圖中,群友口中所說(shuō)的字節(jié)面試官的這種說(shuō)法是否靠譜呢?

一、很顯然不靠譜

從功能實(shí)現(xiàn)的角度上來(lái)說(shuō),上面那一段代碼,其實(shí)是沒(méi)有任何的問(wèn)題的。

當(dāng)組件重新渲染時(shí),hook 會(huì)不會(huì)重新執(zhí)行?當(dāng)然會(huì)。

但是 hook 重新執(zhí)行,狀態(tài)會(huì)不會(huì)發(fā)生變化?不會(huì)。

這里我們討論的是由其他狀態(tài)的變化導(dǎo)致組件 re-render,從而導(dǎo)致 toggle 的狀態(tài)被重置或者變化。

在 React 中,hook 是基于閉包來(lái)實(shí)現(xiàn),因此幾乎每個(gè) hook 理論上都具有緩存能力。我們常用的這些 hook:useState、useRef useReducer useEffect useMemo useCallback 他們都有一些共性,那就是緩存能力。然后在語(yǔ)義上有一些差異。

面試官這樣的說(shuō)法,很明顯是在學(xué)習(xí)的時(shí)候,跟許多人犯了同樣一個(gè)錯(cuò)誤,只關(guān)注了他們差異的部分,而沒(méi)有關(guān)注他們共性的部分。

因此,在群友的這段實(shí)現(xiàn)中,如果由其他狀態(tài)引發(fā)的 hook 重新執(zhí)行,useToggle 的狀態(tài)會(huì)被 useState 緩存,狀態(tài)本身的值不會(huì)發(fā)生變化。否則,React 的根基都要被動(dòng)搖了。

那么面試官為什么要這樣說(shuō)呢?

一種可能就是面試官本身在工作實(shí)踐中沒(méi)有正確理解 React 的 hook,并且過(guò)于依賴了 useMemo useCallback,忽視了其他 hook 的緩存能力導(dǎo)致了錯(cuò)誤的解讀。

另外一種情況就是在沒(méi)有得到自己想要的答案時(shí),自動(dòng)切入了壓力測(cè)試環(huán)節(jié),試圖通過(guò)否定候選人逼問(wèn)出滿意的答案?;蛘咄ㄟ^(guò)壓力測(cè)試觀察候選人的知識(shí)面中更多的維度。

二、有其他實(shí)現(xiàn)嗎

有的。該群友找到了 ahook 的實(shí)現(xiàn),代碼如下:

function useTgoggle2(value: boolean, reverseValue?: boolean) {
  const [state, setState] = useState(value)

  const actions = useMemo(() => {
    const reverseValueOrigin = reverseValue === undefined ? !value : reverseValue;

    const toggle = () => {
      setState(prev => {
        return prev === value ? reverseValueOrigin : value
      })
    }
    return toggle
  }, [])

  return {state, actions}
}

和他寫的版本相比,代碼看上去豐滿了許多。一看就很高端。

但是另他想不通的地方在于,使用了 useMemo 之后,和他寫的那個(gè)版本,有什么區(qū)別嗎?或者說(shuō),有什么好處嗎?

他的第一個(gè)解讀是,useMemo 因?yàn)榫彺媪撕瘮?shù),所以減少了函數(shù)的重復(fù)聲明。

這種理解對(duì)不對(duì)呢?錯(cuò)。

許多人都會(huì)有這樣的誤解。事實(shí)卻是,useMemo useCallback 不會(huì)減少函數(shù)的聲明。

我們把匿名函數(shù),換成一個(gè)有名字的函數(shù),就能快速理解了。

function xxx() {
  const reverseValueOrigin = reverseValue === undefined ? !value : reverseValue;

  const toggle = () => {
    setState(prev => {
      return prev === value ? reverseValueOrigin : value
    })
  }
  return toggle
}

const actions = useMemo(xxx, [])

實(shí)際上在 useMemo 執(zhí)行之前,函數(shù) xxx 都會(huì)重新聲明。包括 useMemo 傳入的第二個(gè)參數(shù)的空數(shù)組,它也是被重新聲明的。

useMemo 控制的是賦值次數(shù),而不是聲明次數(shù)。

既然這樣,又不能減少函數(shù)聲明次數(shù),那 useMemo 的作用在哪里呢?

在這個(gè)案例中,他的作用就是:保持 actions 的引用穩(wěn)定。當(dāng)組件重新渲染時(shí),actions 的引用不會(huì)因?yàn)?nbsp;re-render 而發(fā)生變化。

這樣,當(dāng)使用者將 actions 作為參數(shù)傳遞給其他組件時(shí),可以保證 actions 的引用是沒(méi)有發(fā)生變化的。

const {state, actions} = useToggle(true)

...

<OtherComponent actinotallow={actions} />

那么這個(gè)時(shí)候,如果我們?cè)诼暶?nbsp;OtherComponent 時(shí)使用了 memo,OtherComponent 就不會(huì)因?yàn)楦附M件的 re-render 而重新渲染。

這里需要明確的是,單獨(dú)使用 memo 是沒(méi)有用的。關(guān)于更具體的細(xì)節(jié),在我們之前的性能優(yōu)化章節(jié)中有詳細(xì)聊到。

當(dāng)然實(shí)際上這里就涉及到另外一個(gè)問(wèn)題的探討,我們是否應(yīng)該在工具庫(kù)底層使用 useCallback 或者 useMemo 來(lái)緩存函數(shù)的引用呢?

實(shí)際上在付費(fèi)群里我們?cè)?jīng)對(duì)這個(gè)問(wèn)題也有過(guò)爭(zhēng)議。

我個(gè)人的觀點(diǎn)是:沒(méi)有必要。因?yàn)閷?duì)于使用者而言,我們想要保證性能優(yōu)化的目標(biāo)達(dá)成,那么就必須同時(shí)使用 useMemo/useCallback + memo。他們兩的共同作用下,能減少函數(shù)的 re-render,從而達(dá)到性能優(yōu)化的目的。

一種情況是,需要這樣做的場(chǎng)景很少。

另外一種情況是,這可能對(duì)使用者造成誤解。認(rèn)為只需要 memo 就可以完成性能優(yōu)化了。

這種優(yōu)化方式不是完全無(wú)感的,他需要使用者配合另外一半。因此這就要求使用者必須完全了解工具庫(kù)的底層實(shí)現(xiàn)才可以完美的配合你?;蛘吒斆鞯氖褂谜咭膊粫?huì)關(guān)注你底層是怎么實(shí)現(xiàn),他自己又單獨(dú)包裹一層 useMemo/useCllback。

三、面試時(shí)答案被否定

咋說(shuō)呢,這個(gè)現(xiàn)象其實(shí)非常普遍。

很多人在面試的時(shí)候,特別是在面一些好團(tuán)隊(duì)時(shí),遇到這種情況都會(huì)很懵逼。被人否定之后就習(xí)慣性地懷疑自己的答案有問(wèn)題。從而導(dǎo)致后面的回答因?yàn)榫o張和自我懷疑陷入一種惡性循環(huán),給人一種整場(chǎng)表現(xiàn)都很差的感覺(jué)。

有幾種不同的情況會(huì)出現(xiàn)這種局面。

有的面試官比較善于抓住候選人的缺點(diǎn)不停拷打,進(jìn)而證明候選人能力不足。這其實(shí)違背了面試的本質(zhì)。好的面試官反而更應(yīng)該懂得如何挖掘候選人的優(yōu)勢(shì),而不是在候選人不擅長(zhǎng)的點(diǎn)上反復(fù)糾纏。

當(dāng)然,這也可以理解,現(xiàn)在越來(lái)越多的面試官會(huì)陷入這種困境,很大一部分原因是因?yàn)樘嗟那舐氄咴诤?jiǎn)歷、面試中夸大自己的能力,把本來(lái)不屬于自己的項(xiàng)目經(jīng)歷包裝成自己的,面試官與求職者信任關(guān)系的破裂,是主要是的因素之一。

當(dāng)然,還有一部分原因是因?yàn)樾枰诰騽e人的優(yōu)勢(shì)對(duì)面試官本身的個(gè)人能力有非常高的要求,并不是每個(gè)面試官都具備這樣的能力。因此,在這種情況下,一個(gè)比較好的技巧和方式就是主動(dòng)自己先明確好自己的優(yōu)勢(shì)在哪里,并且在聊天過(guò)程中主動(dòng)展示。

除此之外,也包括部分求職者,屬于是找了半天,渾身下上就沒(méi)可挖掘的優(yōu)勢(shì)。

壓力測(cè)試?;蛘哒f(shuō),故意在面試過(guò)程中給求職者施加壓力。讓求職者認(rèn)為自己在這場(chǎng)面試?yán)锉憩F(xiàn)得不好。哪怕有的面試官對(duì)求職者非常欣賞,也不會(huì)表現(xiàn)出來(lái)。

所以很多時(shí)候,有的人雖然自己拿到了 offer,但是自己都感覺(jué)非常意外,因?yàn)樽晕腋杏X(jué)確實(shí)面試表現(xiàn)不是很好,在這種情況下還能拿到 offer,實(shí)屬是萬(wàn)萬(wàn)沒(méi)想到。

當(dāng)然,為什么要這樣做,不同的團(tuán)隊(duì)有不同的原因,可能是為了看看別人在壓力環(huán)節(jié)下的表現(xiàn),可能是為了更好的打壓薪資,或者是為了讓求職者更加珍惜這個(gè)工作機(jī)會(huì)等等。

但是壓力測(cè)試也不是每個(gè)面試官都能輕松拿捏的,經(jīng)常容易玩崩,讓別人對(duì)你這里的面試體驗(yàn)感覺(jué)非常差。

確實(shí)是求職者思路不對(duì),回答錯(cuò)了。這種情況下最好是能在面試官的引導(dǎo)下快速思考錯(cuò)誤原因,并給出正確的解法。當(dāng)然,如果實(shí)在不行,就直接承認(rèn)自己確實(shí)這方面比較薄弱比較好。但是不少人為了補(bǔ)救,會(huì)多說(shuō)很多不沾邊的內(nèi)容,反而會(huì)錯(cuò)得更離譜。

四、總結(jié)

許多人雖然掌握了某些知識(shí),但是沒(méi)有構(gòu)建完整的知識(shí)體系,因此在面對(duì)別人反問(wèn)或者質(zhì)問(wèn)時(shí)會(huì)表現(xiàn)得非?;艁y。

完善自己的知識(shí)體系,對(duì)自己所表達(dá)的觀念和結(jié)論有篤定的判斷,可以避免在這種情況之下讓溝通往更壞的情況發(fā)展。

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

2022-04-08 07:52:17

CSS面試題HTML

2023-02-04 18:24:10

SeataJava業(yè)務(wù)

2024-10-11 17:09:27

2011-05-23 11:27:32

面試題面試java

2018-03-06 15:30:47

Java面試題

2015-09-02 14:09:19

面試題程序設(shè)計(jì)

2021-04-30 08:22:36

異步求和函數(shù)

2009-08-11 10:12:07

C#算法

2009-08-11 14:59:57

一道面試題C#算法

2019-09-02 15:06:16

面試字節(jié)跳動(dòng)算法

2021-05-31 07:55:44

smartRepeatJavaScript函數(shù)

2023-08-01 08:10:46

內(nèi)存緩存

2009-08-11 15:09:44

一道面試題C#算法

2017-11-21 12:15:27

數(shù)據(jù)庫(kù)面試題SQL

2021-03-16 05:44:26

JVM面試題運(yùn)行時(shí)數(shù)據(jù)

2021-10-28 11:40:58

回文鏈表面試題數(shù)據(jù)結(jié)構(gòu)

2022-02-08 18:09:20

JS引擎解析器

2011-03-02 10:58:16

SQL server入門面試題

2017-03-10 09:33:16

JavaScript類型

2017-09-13 07:15:10

Python讀寫文件函數(shù)
點(diǎn)贊
收藏

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