小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
正文
话不多说, 直接进入正题, 在vue-next仓库中里边的package->shared->src->shapeFlags.ts里边写了这样一段枚举:
export const enum ShapeFlags {
ELEMENT = 1,
FUNCTIONAL_COMPONENT = 1 << 1,
STATEFUL_COMPONENT = 1 << 2,
TEXT_CHILDREN = 1 << 3,
ARRAY_CHILDREN = 1 << 4,
SLOTS_CHILDREN = 1 << 5,
TELEPORT = 1 << 6,
SUSPENSE = 1 << 7,
COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8,
COMPONENT_KEPT_ALIVE = 1 << 9,
COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
}
这个枚举就是通过移位运算符去运算后获取一个值作为枚举的值. 具体运算出来的结果大概是这样的:
| ShapeFlags | 左移运算 | 计算结果 | 二进制 |
|---|---|---|---|
| FUNCTIONAL_COMPONENT | 1 << 1 | 2 | 0010 |
| STATEFUL_COMPONENT | 1 << 2 | 4 | 0100 |
| TEXT_CHILDREN | 1 << 3 | 8 | 1000 |
| ARRAY_CHILDREN | 1 << 4 | 16 | 0001 0000 |
| TELEPORT | 1 << 5 | 32 | 0010 0000 |
| SUSPENSE | 1 << 6 | 64 | 0100 0000 |
| COMPONENT_SHOULD_KEEP_ALIVE | 1 << 7 | 128 | 1000 0000 |
| COMPONENT_KEPT_ALIVE | 1 << 8 | 256 | 0001 0000 0000 |
| 这样看就很清楚了,左移运算每加1的话,二进制都会进1位。 |
COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
然后我们接着看,在枚举以后一项,有一个按位或(|)运算描述了COMPONENT,这里就有一个位运算里边的小技巧了。 在这里COMPONENT表示的就是STATEFUL_COMPONENT和FUNCTIONAL_COMPONENT都属于COMPONENT. 在后边代码里边如果要判断是否是COMPONENT的话,就这样很冗余的去判断了
if (type === ShapeFlags.STATEFUL_COMPONENT || type === ShapeFlags.FUNCTIONAL_COMPONENT) {
// dosomething
}
我们可以去这样写:
if (type & ShapeFlags.COMPONENT) {
// dosomething
}
如果type是STATEFUL_COMPONENT或者FUNCTIONAL_COMPONENT的话,则会得到一个非0值。 非0的话,则为ture,可以进入if判断的代码块里边去。 如果不是的话,则会返回0. 则不会进入判断里边。 这种技巧可以帮我们省下很冗余的代码。 我们在项目里边也会遇到有很多状态的情况,肯定存在需要判断状态是否是某一些状态的时候,去处理一些逻辑。 所以我们可以很好的使用这种方式去让代码更加简洁,并且可读性更高。
另外还有一个按非运算符~在项目里边也很好用。 比如我们一般写代码的话,判断数组里边是否存在某一个值,是这样判断的
let arr = [1,2,3]
if (arr.indexOf(2) > -1) {
console.log('dosomething')
}
其实我们可以写的更简洁一点:
let arr = [1,2,3]
if (~arr.indexOf(2)) {
console.log('dosomething')
}
原理其实就是如果不存在的话,indexOf会返回-1给我们, 那么~-1的话,算出来就是0了,0则是false,不会进入代码块里边。 如果存在的话,则是一个不为-1的其他数字, 那么~index则是一个非0的数字。 所以会进入if代码块。
结语
看别人的代码,确实还是能学到很多东西的。 尤其是像vue这种优秀的代码仓库。 很建议大家一起去多阅读这种优秀的源码。 一起加油! 那么今天就到这里了。 明天见!