关于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源码正在阅读中,有望一两个月把所有成果放出来,有兴趣的可以关注我
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。