925 字
5 分钟
使用位运算管理类型或状态
前 言在许多场景,尤其前端组件库开发中,使用位运算管理 类型/状态 是一种非常高效和优雅的方式,特别适合处理”多状态共存” 或 “类型组合”。这种方式利用二进制位的独立性,通过位运算实现状态的组合、判断和修改,具有性能高、代码简洁、扩展性强的特点。
一、基本原理
TIP 用二进制的每一位来代表一个独立的状态/类型,然后通过位运算(与、或、非、异或、与非等)来实现状态的判断/组合/切换等操作
- 每个状态 / 类型用
2^n
(即1 << n
)表示,确保二进制中只有一位为1
(互不干扰)。- 用一个数字(二进制)存储多个状态的组合(每一位代表该状态是否生效)。
- 通过位运算快速操作:
- 组合状态:
|
(或运算,叠加状态)- 检查状态:
&
(与运算,判断是否包含某状态)- 移除状态:
& ~
(与非运算,清除某状态)- 切换状态:
^
(异或运算,反转某状态)
二、简单示例
这里我们以一个Button组件状态管理场景举例:
1. 定义状态枚举
// 每个状态对应一个二进制位
enum ButtonStatus {
Disabled = 1 << 0, // 1 二进制: 0001
Loading = 1 << 1, // 2 二进制: 0010
Selected = 1 << 2, // 4 二进制: 0100
Highlight = 1 << 3 // 8 二进制: 1000
}
2. 状态操作方法
class Button {
private status: number = 0
// 判断
hasStatus(target: ButtonStatus): boolean {
return (this.status & target) !== 0
}
// 组合:可同时添加多个
addStatus(...states: ButtonStatus[]): void {
states.forEach((state) => {
this.status |= state
})
}
// 删除:可同时移除多个
removeStatus(...states: ButtonStatus[]): void {
states.forEach((state) => {
this.status &= ~state
})
}
// 切换: 存在则移除,不存在则添加
toggleStatus(state: ButtonStatus): void {
this.status ^= state
}
}
三、应用场景
除了上面举例的场景外,还有很多类似的场景都可以考虑使用,比如:
1. 权限管理
用位值表示不同权限(如查看、编辑、删除),用户的权限集合为多个位的组合,通过位运算快速判断是否有权限
enum Permission {
View = 1 << 0, // 1
Edit = 1 << 1, // 2
Delete = 1 << 2, // 4
Admin = 1 << 3 // 8
}
// 用户权限:可以查看和编辑
const userPerms = Permission.View | Permission.Edit;
// 判断是否有权限删除
const canDelete = (userPerms & Permission.Delete) !== 0; // false
2.事件类型组合
enum EventType {
Click = 1 << 0, // 点击
Hover = 1 << 1, // 悬浮
Focus = 1 << 2 // 聚焦
}
// 监听「点击」和「聚焦」事件
const listenEvents = EventType.Click | EventType.Focus;
// 触发事件时判断类型
function handleEvent(type: EventType) {
if (type & listenEvents) {
console.log('处理点击');
}
}
3.特征标记
enum Feature {
DarkMode = 1 << 0, // 深色模式
NewUI = 1 << 1, // 新UI
Beta = 1 << 2 // beta功能
}
// 为用户开启「深色模式」和「新UI」
const userFeatures = Feature.DarkMode | Feature.NewUI;
// 检查是否开启新UI
if (userFeatures & Feature.NewUI) {
renderNewUI();
}
四、优缺点总结
适用场景 状态数量少(通常≤20 种)、状态间独立无依赖、需要频繁组合 / 检查状态的场景
优势
- 性能高效:位运算为底层操作,比数组 / 对象的遍历判断更快
- 代码简洁:一行位运算代替多行条件判断,减少冗余逻辑
- 扩展性强:新增状态只需添加一个位值,无需修改已有判断逻辑
- 内存友好:一个数字即可存储多个状态,比对象 / 数组更节省空间
不足
- 状态数量有限: 受限于整数位数
- 可读性较低