React原始碼閱讀之:複合型別方案設計

Jokcy發表於2018-09-05

關於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,其他位都是00bxxx是原生二進位制字面量的表示方法

那麼回過頭去我們再看上面兩句表示式

workInProgress.effectTag |= Ref
// 也就是
workInProgress.effectTag = workInProgress.effectTag | RefRef

我們隨便拿兩個值來舉例,比如PlacementUpdate,也就是0b00000000010 | 0b00000000100那麼得到的結果是什麼呢?0b00000000110,也就等於PlacementAndUpdate。所以這時候大家知道為什麼大部分的值1所在的位置不一樣了吧,因為其實每一位的1代表一種屬性,把他們結合在一起就代表有多種屬性,不會有重複。

同樣的對於第二個表示式

(workInProgress.effectTag & DidCapture) !== NoEffect

我們拿UpdateDidCapture來進行&操作,那麼得到的結果就很明顯了,所有位都是0,所以後期的&操作是用來判斷在某個變數中是否含有某個屬性的。比如這裡就是判斷workInProgress.effectTag中是否含有DidCapture這個屬性。

這種設計方式我覺得挺有參考意義的,可以用在類似許可權系統上。大概現在很多許可權系統已經這麼做了吧,只是我不知道。。。

React原始碼正在閱讀中,有望一兩個月把所有成果放出來,有興趣的可以關注我

相關文章