關於React中一些程式碼設計
最近在看React的原始碼,注意到了一些有意思的細節,比如經常會出現的一下比較和賦值程式碼
workInProgress.effectTag |= Ref
(workInProgress.effectTag & DidCapture) !== NoEffect
對於平時基本上沒怎麼用到過移位運算的我一開始表示這是啥?為啥要這麼設計?
我們先來看一下,這個effectTag
具體會有那些值
// Don`t change these two values. They`re used by React Dev Tools.
export const NoEffect = /* */ 0b00000000000;
export const PerformedWork = /* */ 0b00000000001;
// You can change the rest (and add more).
export const Placement = /* */ 0b00000000010;
export const Update = /* */ 0b00000000100;
export const PlacementAndUpdate = /* */ 0b00000000110;
export const Deletion = /* */ 0b00000001000;
export const ContentReset = /* */ 0b00000010000;
export const Callback = /* */ 0b00000100000;
export const DidCapture = /* */ 0b00001000000;
export const Ref = /* */ 0b00010000000;
export const Snapshot = /* */ 0b00100000000;
// Union of all host effects
export const HostEffectMask = /* */ 0b00111111111;
export const Incomplete = /* */ 0b01000000000;
export const ShouldCapture = /* */ 0b10000000000;
這麼一看貌似好像有點意思,可以看到大部分的值都只有一位是1
,其他位都是0
,0bxxx
是原生二進位制字面量的表示方法
那麼回過頭去我們再看上面兩句表示式
workInProgress.effectTag |= Ref
// 也就是
workInProgress.effectTag = workInProgress.effectTag | RefRef
我們隨便拿兩個值來舉例,比如Placement
和Update
,也就是0b00000000010 | 0b00000000100
那麼得到的結果是什麼呢?0b00000000110
,也就等於PlacementAndUpdate
。所以這時候大家知道為什麼大部分的值1
所在的位置不一樣了吧,因為其實每一位的1
代表一種屬性,把他們結合在一起就代表有多種屬性,不會有重複。
同樣的對於第二個表示式
(workInProgress.effectTag & DidCapture) !== NoEffect
我們拿Update
和DidCapture
來進行&
操作,那麼得到的結果就很明顯了,所有位都是0
,所以後期的&
操作是用來判斷在某個變數中是否含有某個屬性的。比如這裡就是判斷workInProgress.effectTag
中是否含有DidCapture
這個屬性。
這種設計方式我覺得挺有參考意義的,可以用在類似許可權系統上。大概現在很多許可權系統已經這麼做了吧,只是我不知道。。。
React原始碼正在閱讀中,有望一兩個月把所有成果放出來,有興趣的可以關注我