JS位运算应用场景

准备知识

2进制和16进制

  • 0x开头是16进制
0x2000000
  • 0b开头是2进制
export const Deletion = 0b00000000000000001000;

进制转换

数字转换成字符串

numObj.toString([radix])

  • 十进制转换成二进制
var num=100;
num.toString(2); // "1100100"

解析一个字符串并返回指定基数的十进制整数

Number.parseInt(string[, radix])

  • 16进制转换成十进制
var num=2000000; 
parseInt(num,16); // 33554432

计算

&:按位与

var a = 0b100;
var b = 0b1100;
var res = a & b;
console.log(res.toString(2));// 100

|:按位或

var a = 0x100;
var b = 0x2000;
var res = a | b;
console.log(res.toString(16));// 2100

应用场景

描述

用于表示各种状态的叠加态

通常解法

通俗一点说,今天吃的水果沙拉有西瓜、芒果、草莓。
那用js怎么表示这样的状态呢?通常情况我们肯定是使用数组:

var watermelon = '1';
var mango = '2';
var strawberry = '3';

var salad = [watermelon, mango, strawberry];

判读沙拉里是否有芒果

salad.includes(mango);

这样有啥问题吗?
又不是不能用,倒也没啥大的问题。但是对于一段高频代码来说,使用数组反复做push、pop、includes这种操作只是为了维护某个状态,并不是最优解。

位运算解法

flags

在React中有这样的应用。
fiber可以理解为React中虚拟Dom节点,使用fiber.flags来描述该节点要执行DOM操作的具体类型。

/* react/packages/react-reconciler/src/ReactFiberFlags.js */
// DOM需要插入到页面中
export const Placement = /*                    */ 0b00000000000000000010;
// DOM需要更新
export const Update = /*                       */ 0b00000000000000000100;
// DOM需要插入页面中并更新
export const PlacementAndUpdate = /*           */ Placement | Update;
// DOM需要删除
export const Deletion = /*                     */ 0b00000000000000001000;

bitField

bluebird中对于promise状态的部分描述如下

/* bluebird-master/src/constants.js */
CONSTANT(IS_FULFILLED, 0x2000000|0);
CONSTANT(IS_REJECTED, 0x1000000|0);
CONSTANT(WILL_BE_CANCELLED, 0x800000|0);
CONSTANT(IS_FINAL, 0x400000|0);
CONSTANT(IS_BOUND, 0x200000|0);
/* bluebird-master/src/promise.js */
Promise.prototype._setFulfilled = function () {
    this._bitField = this._bitField | IS_FULFILLED;
    this._fireEvent("promiseFulfilled", this);
};

Promise.prototype._isFollowing = function () {
    return (this._bitField & IS_FOLLOWING) === IS_FOLLOWING;
};

状态判定

commitMutationEffects

水果沙拉位运算应用

观察上面的例子,可以把数组解法改成这样

var watermelon = 0b001;
var mango = 0b010;
var strawberry = 0b100;

var salad = watermelon| mango|strawberry;

var res = (salad & mango) === mango;
console.log(res); // true

最大整数范围

js中能表示的最大整数为2^53
所以使用这个方法按每个状态只有一个1来算,能存53个状态。

THE END

你可能感兴趣的:(JS位运算应用场景)