# 位运算符
位运算符将它的操作数视为 32 位元的二进制串(0 和 1 组成)而非十进制、八进制或十六进制数。例如:十进制数字 9 用二进制表示为 1001,位运算符就是在这个二进制表示上执行运算,但是返回结果是标准的 JavaScript 数值。
所有 JavaScript 数字存储为根为 10 的 64(8 比特)浮点数。JavaScript 不是类型语言。与许多其他编程语言不同,JavaScript 不定义不同类型的数字,比如整数、短、长、浮点等等。 整数精度(不使用小数点或指数计数法)最多为 15 位。小数精度的最大位数是 17,但是浮点运算并不总是 100% 准确。 位运算直接对二进制位进行计算,位运算直接处理每一个比特位,是非常底层的运算,好处是速度极快,缺点是很不直观,许多场合不能够使用。 位运算只对整数起作用,如果一个运算数不是整数,会自动转为整数后再运行。 在 JavaScript 内部,数值都是以 64 位浮点数的形式储存,但是做位运算的时候,是以 32 位带符号的整数进行运算的,并且返回值也是一个 32 位带符号的整数。
# 位操作符含义
按位与(AND):使用符号 "&" 表示,将两个操作数的对应位进行逻辑与运算。只有当两个操作数的对应位都为1时,结果位才为1,否则为0。 按位或(OR):使用符号 "|" 表示,将两个操作数的对应位进行逻辑或运算。只要两个操作数的对应位中至少有一个为1,结果位就为1,否则为0。 按位异或(XOR):使用符号 "^" 表示,将两个操作数的对应位进行逻辑异或运算。当两个操作数的对应位不同时,结果位为1,否则为0。 按位取反(NOT):使用符号 "~" 表示,对操作数的每个位进行逻辑取反运算。将0变为1,将1变为0。 左移(左位移):使用符号 "<<" 表示,将操作数的二进制表示向左移动指定的位数。左移操作会在右侧填充0,并将左侧位移出的位丢弃。 右移(右位移):使用符号 ">>" 表示,将操作数的二进制表示向右移动指定的位数。右移操作会在左侧填充0或符号位,并将右侧位移出的位丢弃。
# 异或运算有以下三个性质:
- 任何数和 0 做异或运算,结果仍然是原来的数,即 a ^ 0 = a。
- 任何数和其自身做异或运算,结果是 0,即 a ^ a = 0。
- 异或运算满足交换律和结合律,即 a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c。
# 取整
使用 ~、>>、<<、>>>、| 来取整。
console.log(~~6.78); // 6
console.log(6.78 >> 0); // 6
console.log(6.78 << 0); // 6
console.log(6.78 | 0); // 6
// >>>不可对负数取整
console.log(6.78 >>> 0); // 6
# 值交换
使用按位异或 ^ 来完成值交换,异或还经常被用于加密。
let a = 5;
let b = 8;
a ^= b;
b ^= a;
a ^= b;
console.log(a); // 8
console.log(b); // 5
# 颜色值转换
使用 &、>>、| 来完成 RGB 值和 16 进制颜色值之间的转换
/**
* 16进制颜色值转RGB
* @param {String} hex 16进制颜色字符串
* @return {String} RGB颜色字符串
*/
function hexToRGB(hex) {
var hexx = hex.replace('#', '0x');
var r = hexx >> 16;
var g = (hexx >> 8) & 0xff;
var b = hexx & 0xff;
return `rgb(${r}, ${g}, ${b})`;
}
/**
* RGB颜色转16进制颜色
* @param {String} rgb RGB进制颜色字符串
* @return {String} 16进制颜色字符串
*/
function RGBToHex(rgb) {
var rgbArr = rgb.split(/[^\d]+/);
var color = (rgbArr[1] << 16) | (rgbArr[2] << 8) | rgbArr[3];
return '#' + color.toString(16);
}
// -------------------------------------------------
hexToRGB('#ffffff'); // 'rgb(255,255,255)'
RGBToHex('rgb(255,255,255)'); // '#ffffff'
# 正负判断
function isPos(n) {
return n === n >>> 0 ? true : false;
}
isPos(-1); // false
isPos(1); // true
# 判断符号是否相同
通常, 比较两个数是否符号相同, 我们使用 x * y > 0 来判断即可. 但如果利用按位异或 ^, 运算速度将更快。
function isSameSymbol(x, y) {
return (x ^ y) > 0;
}
isSameSymbol(-7, 9); // false
# 判断是否为 2 的幂
function isPowerOfTwo(n) {
return (n & (n - 1)) === 0;
}
// false
# 判断奇偶
使用 & 运算符判断一个数的奇偶
如果把 n 以二进制的形式展示的话,其实我们只需要判断最后一个二进制位是 1 还是 0 就行了。
// 偶数 & 1 = 0
// 奇数 & 1 = 1
console.log(2 & 1); // 0
console.log(3 & 1); // 1
# 判断索引是否存在
这是一个很常用的技巧,如判断一个数是否在数组里面:
// 如果url含有 ? 号,则后面拼上&符号,否则加上?号
url += ~url.indexOf('?') ? '&' : '?';
因为:~-1 === 0