你可能不知道的JavaScript位运算符详解

目录
  • 概览
  • 位操作符概览
  • 位操作支持多少位?
  • 负数的无符号右移
    • -2 >>> 1为什么输出2147483647?
  • 状态控制
  • 权限控制
  • 判断奇偶数
  • 交换两个变量的值
  • 判断整数是否相等
  • 判断是否为负数
  • 正浮点数取整
  • 正负浮点数取整
  • 十进制转换成二进制
  • 二进制转换成十进制
  • 参考

概览

本文详细剖析JavaScript的位运算符,其涉及的计算机原理和操作效果。

然后从实战的角度出发,罗列相关的应用场景。

位操作符概览

运算符 描述 示例
按位与(AND) 两个操作数对应的比特位都是1时,结果才为1,否则为0 1011 & 0111 = 0011
按位或(OR) 两个操作数对应的比特位至少有一个1时,结果为1,否则为0 1011 | 0111 = 1111
按位异或(XOR) 两个操作数对应的比特位有且只有一个1时,结果为1,否则为0 1011 ^ 0111 = 1100
按位非(NOT) 逐个反转操作数的比特位,即0变成1,1变成0 ~1011 = 0100
左移 通过从右推入零向左位移,并使最左边的位脱落。 1011 << 1 = 10110
有符号右移 通过从左推入最左位的拷贝来向右位移,并使最右边的位脱落。 01011 >> 1 = 00101
无符号右移 通过从左推入零来向右位移,并使最右边的位脱落。 01011 >>> 1 = 00101

位操作支持多少位?

js只支持32位二进制数的位操作,也即能处理的最大十进制数字是 4294967295

parseInt('11111111111111111111111111111111', 2);  // 4294967295

验证下超过32位二进制数的位操作:

// 33位二进制数,得到十进制数字 8589934591
parseInt('111111111111111111111111111111111', 2); // 8589934591

// 对数字进行无符号位右移
8589934591 >>> 0; // 4294967295
4294967295 >>> 0; // 4294967295

可以看出,数字 85899345914294967295 进行 无符号位右移0位 操作,得到的结果是一样的。

产生这样结果的原因,是js的位操作实现,只支持32位

注意:ECMAScript 中的所有数值都以IEEE754 64位格式存储,只是在位操作的时候 ,需要转换成32位进行操作。

负数的无符号右移

-2 >>> 1为什么输出2147483647?

-2在运算中,是用补码表示,即1 1111111111111111111111111111110

其中,第1位是符号位。 符号位1代表当前数字是负数。

-2无符号右移1位,则最右边的0脱落,剩下31位1111111111111111111111111111111,接着,在左侧补0,得到01111111111111111111111111111111

01111111111111111111111111111111代表十进制数2147483647

状态控制

场景:

以下使用React+TypeScript,实现游戏状态机的状态流转,根据状态渲染对应的操作按钮。

// 游戏状态定义
export enum GAME_STATE{
   INIT = 1 << 0,      // 二进制表示:00001
   JOIN = 1 << 1,      // 二进制表示:00010
   PREPARE = 1 << 2,   // 二进制表示:00100
   PLAY = 1 << 3,      // 二进制表示:01000
}
// 根据状态渲染按钮
function RenderButton({state, changeState}){
	if((state & GAME_STATE.PLAY) === GAME_STATE.PLAY){
		return null;
	}

	if((state & GAME_STATE.INIT) === GAME_STATE.INIT){
		return <button
				onClick={() => changeState(GAME_STATE.JOIN)}
		    >加入游戏</button>
	}

	if((state & GAME_STATE.JOIN) === GAME_STATE.JOIN){
		return <button
				onClick={() => changeState(GAME_STATE.PREPARE)}
			>准备游戏</button>
	}

	if((state & GAME_STATE.PREPARE) === GAME_STATE.PREPARE){
		return <button
				onClick={() => changeState(GAME_STATE.PLAY)}
			>开始游戏</button>
	}

	return null;
}

// 渲染游戏页面
function Page(){
	const state = useRef(GAME_STATE.INIT);

	const changeState = useCallback((newState) => {
		state.current = newState;
	}, [state]);

	return (<div>
		// ....other code
		<RenderButton state={state.current} changeState={changeState} />
	</div>);
}

权限控制

设计一个权限控制,用于不同角色对网站文章的权限分配。

export enum ARTICLE_RULE{
	VIEW = 1 << 0,     // 查看文章
	EDIT = 1 << 1,     // 编辑文章
	PUBLISH = 1 << 2,  // 发布文章
	DELETE = 1 << 3,   // 删除文章
} 

export enum ROLE{
	GUEST = ARTICLE_RULE.VIEW,    // 访客
	ADMIN = ARTICLE_RULE.VIEW | ARTICLE_RULE.EDIT | ARTICLE_RULE.PUBLISH | ARTICLE_RULE.DELETE,  // 超级管理员
	OPERATOR = ARTICLE_RULE.VIEW | ARTICLE_RULE.EDIT | ARTICLE_RULE.PUBLISH,  // 运营
}
if(user.role === 'admin'){
	console.log("user拥有admin权限");
	user.rule = ROLE.ADMIN; // 赋予角色权限
}

if((user.rule & ARTICLE_RULE.DELETE) === ARTICLE_RULE.DELETE){
	console.log("user拥有删除文章权限");
}

判断奇偶数

奇数,最末尾1位,一定是1

所以将数字与1(二进制表示为:00000000000000000000000000000001)作位操作&

如果等于1,则是奇数。

function isOdd(number){
	return number & 1 === 1;
}

交换两个变量的值

let a = 1;
let b = 2;

a = a ^ b;  // 这一步,a缓存了 a ^ b 的结果
b = a ^ b;  // 等价为: b = a ^ b ^ b, 其中 b ^ b = 0; 所以 b = a ^ 0 = a
a = a ^ b;  // 同上

判断整数是否相等

function isEqual(number1, number2){
	return (number1 ^ number2) === 0;
}

判断是否为负数

如果是负数,则对数字进行 无符号右移 位操作,会变成一个新的数字。

所以,如果是负数,则两个数字不相等。

function isMinus(number){
	return number !== (number >>> 0);
}

正浮点数取整

function toInt(floatNumber){
	return floatNumber >>> 0;
}

正负浮点数取整

function toInt(floatNumber){
	return floatNumber | 0;
}
function toInt(floatNumber){
	return ~~floatNumber;
}
function toInt(floatNumber){
	return floatNumber >> 0;
}

十进制转换成二进制

function dec2bin(dec){
	return (dec).toString(2);
}

二进制转换成十进制

function bin2dec(bin){
	return parseInt(`${bin}`, 2)
}

参考

到此这篇关于JavaScript位运算符的文章就介绍到这了,更多相关JS位运算符内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • javaScript中一些常见的数据类型检查校验

    目录 前言 常见的几种数据校验方式 typeof操作符 instanceof constructor call && apply Object.prototype.toString结合Function.prototype.call && apply 其他校验数据类型的方法: 总结 源码地址 前言 在JavaScript中,数据类型分为两大类,一种是基础数据类型,另一种则是复杂数据类型,又叫引用数据类型 基础数据类型:数字Number 字符串String 布尔Boolean

  • javascript数据类型基础示例教程

    js中的输入输出语句 方法 说明 归属 alert(msg) 浏览器弹出警示框 浏览器 console.log(msg) 浏览器控制台打印输出信息 浏览器 prompt(info) 浏览器弹出输入框,用户可以输入 浏览器 注:prompt(info)获取的输入都是字符串类型,跟python中的input()类似. <script> prompt("请输入:"); alert('你好呀!小可爱!'); console.log('阿牛最帅啦!'); </script>

  • JavaScript数据类型转换

    目录 一.转换函数 1.parseInt() 2.parseFloat() 3.toString() 二.强制类型转换函数 1.Boolean() 2.Number() 3.String() 一.转换函数 1.parseInt() parseInt()函数可以将任何类型的值转换为整数. 例如: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">

  • JavaScript中7种位运算符在实战的妙用

    目录 位运算符 按位非 - 按位与 & 按位或 | 按位异或 ^ 左移 << 有符号右移 >> 无符号右移 >>> 实战中的妙用 1.判断奇偶数 2. 使用^来完成值的交换 3. 使用~进行判断 4. 使用&.>>.|来完成rgb值和16进制颜色值之间的转换 5. 使用|.~.>>.<<.>>>来取整 本篇文章带大家了解一下JavaScript中的7种位运算符,看看如何妙用这7种位运算符,希望对

  • javascript基础数据类型转换教程示例

    目录 数值型转换为字符串类型 字符串类型转换为数值型 转换为布尔型 结语 数值型转换为字符串类型 方式 说明 案例 toString() 转成字符串 var num =1; alert ( num.toString()); String() 强制转换 转成字符串 var num =1; alert ( String ( num )); 加号拼接字符串 和字符串拼接的结果都是字符串 var num =1; alert ( num +"我是字符串"); // 1.将数字型转换为字符串类型 var n

  • JavaScript详细分析数据类型和运算符

    目录 一.js中的数据类型 1.数值型 2.字符串型 3.逻辑(布尔)型 4.空(null)值 5.未定义(undefined) 6.复合数据类型Object 二.JavaScript中的运算符 1.算数运算符 2.赋值运算符 3.比较运算符 4.逻辑运算符 一.js中的数据类型 1.JS是弱类型的脚本语言,所有的变量对象的数据类型的声明都是var . 2.变量声明时没有确定具体的数据类型,在变量赋值时确定变量具体的数据类型. 五种基本的数据类型 1.数值型 number整数和浮点数统称为数值.

  • JavaScript中的数据类型介绍

    一.基本数据类型(原始值类型) 基本类型:字符串(String).数字(Number).布尔(Boolean).对空(Null).未定义(Undefined).Symbol. 基本类型的变量是存放在栈内存(Stack)里,栈内存中保存了变量标识符和指向堆内存中该对象的指针. 注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值. JavaScript 拥有动态类型.这意味着相同的变量可用作不同的类型: var x; // x 为 undefined var x = 5; /

  • javascript中instanceof运算符的用法详解

    概述 instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上 语法 obj instanceof Object;//true 实例obj在不在Object构造函数中 描述 instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上. 实例 1.instanceof的普通的用法,obj instanceof Object 检测Object.prototype是否存在于参数

  • javascript基本数据类型和对象类型归档问题解析

    javascript的基本数据类型以及引用数据类型,基本数据类型在开发中经常会用到,包括作为变量使用,判断数据类型来处理一些业务等 基本(简单数据类型) undefined,Null,Boolean,Number,String 复杂的数据类型Object undefined undefined 类型只有一个值,即它本身,在使用var声明变量但未给初始值时,这个变量的值为undefined, var msg; console.log(msg==undefined);//true Null Null

  • 你可能不知道的JavaScript位运算符详解

    目录 概览 位操作符概览 位操作支持多少位? 负数的无符号右移 -2 >>> 1为什么输出2147483647? 状态控制 权限控制 判断奇偶数 交换两个变量的值 判断整数是否相等 判断是否为负数 正浮点数取整 正负浮点数取整 十进制转换成二进制 二进制转换成十进制 参考 概览 本文详细剖析JavaScript的位运算符,其涉及的计算机原理和操作效果. 然后从实战的角度出发,罗列相关的应用场景. 位操作符概览 运算符 描述 示例 按位与(AND) 两个操作数对应的比特位都是1时,结果才为

  • C++位运算符详解(异或运算符和移位运算符)

    什么是位运算 位运算符按二进制进行运算,这些运算符只能用于整数类型的操作.如:char,short,int,long 通过位运算符来获取高位值和低位值 int a=0x1234; int high,low; high = (a>>8) &0x00ff; low = a & 0x00ff; 左移运算符和右移运算符(<<和>>) 左移是将一个二进制数,移动若干位,右边空出的位置用0来填补,高位左移溢出应该舍弃该高位. 如:inta = 8, a = 0000

  • HashMap源码中的位运算符&详解

    引言 最近在读HashMap源码的时候,发现在很多运算符替代常规运算符的现象.比如说用hash & (table.length-1) 来替代取模运算hash&(table.length):用if((e.hash & oldCap) == 0)判断扩容后元素的位置等等. 1.取模运算符%底层原理 ​总所周知,位运算&直接对二进制进行运算:而对于取模运算符%:a % b 相当于 a - a / b * b,底层实际上是除法器,究其根源也是由底层的减法和加法共同完成.所以其运行效

  • 你所不知道的Spring自动注入详解

    自动注入和@Autowire @Autowire不属于自动注入! 注入方式(重要) 在Spring官网上(文档),定义了在Spring中的注入方式一共有两种:set方法和构造函数. 也就是说,你想在A类里面注入另外一个B类,无论你是通过写 XML文件,或者通过 @Autowried,他们最终都是通过这个A类的set方法或者构造函数,将B类注入到A类中! 换句话说,你如果A类里面没有setB(B b){-},那你就别想通过set方法把B类注入到A类中 自动注入 首先摆出一个比较颠覆的观点:@Aut

  • 你可能不知道的package.json属性详解

    目录 概述 name version description keywords homepage bugs license 和用户相关的属性:author,contributors files main bin man directories directories.lib directories.bin directories.man directories.doc directories.example repository scripts config dependencies URLsa

  • 你一定不知道的Java Unsafe用法详解

    目录 Unsafe是什么 如何正确地获取Unsafe对象 Unsafe实现CAS锁 使用Unsafe创建对象 Unsafe加载类 总结 Unsafe是什么 首先我们说Unsafe类位于rt.jar里面sun.misc包下面,Unsafe翻译过来是不安全的,这倒不是说这个类是不安全的,而是说开发人员使用Unsafe是不安全的,也就是不推荐开发人员直接使用Unsafe.而且Oracle JDK源码包里面是没有Unsafe的源码的.其实JUC包里面的类大部分都用到了Unsafe,可以说Unasfe是j

  • JavaScript知识点总结(四)之逻辑OR运算符详解

    在JavaScript中,逻辑OR运算符用||表示 var bTrue = true; var bFalse = false; var bResult = bTrue || bFalse; 下面的真值表描述了逻辑AND运算符的行为: 在JavaScript中,0,"",false,null,undefined,NaN均表示false, 可以用如下的代码证明: <script type="text/javascript"> var bFalse = fal

  • Kotlin 语言中调用 JavaScript 方法实例详解

    Kotlin 语言中调用 JavaScript 方法实例详解 Kotlin 已被设计为能够与 Java 平台轻松互操作.它将 Java 类视为 Kotlin 类,并且 Java 也将 Kotlin 类视为 Java 类.但是,JavaScript 是一种动态类型语言,这意味着它不会在编译期检查类型.你可以通过动态类型在 Kotlin 中自由地与 JavaScript 交流,但是如果你想要 Kotlin 类型系统的全部威力 ,你可以为 JavaScript 库创建 Kotlin 头文件. 内联 J

  • 基于C++ bitset常用函数及运算符(详解)

    C++ bitset--高端压位卡常题必备STL ------------------------------------------------------------ 以下内容翻译自cplusplus.com,极大地锻炼了我的英语能力. bitset存储二进制数位. bitset就像一个bool类型的数组一样,但是有空间优化--bitset中的一个元素一般只占1 bit,相当于一个char元素所占空间的八分之一. bitset中的每个元素都能单独被访问,例如对于一个叫做foo的bitset,

  • JavaScript Reduce使用详解

    学会这一个技巧 Reduce 让你开启编程新世界 Learning This Reduce Skill and a Whole New World Will Open up for You

随机推荐