Javascript中的 “&” 和 “|” 详解


Posted in Javascript onFebruary 02, 2017

一、前言:

在文章开始之前,先出几个题目给大家看看:

var num1 = 1 & 0;
console.log(num1); // 0
var num2 = 'string' & 1;
console.log(num2); // 0
var num3 = true & 1;
console.log(num3); // 1 
var num4 = undefined | false;
console.log(num4); // 0 
var num5 = undefined | true;
console.log(num5); // 1 
var num6 = 23 & 5;
console.log(num6); // 5
var num7 = 23 | 5;
console.log(num7); // 23

上面的题目大家都做对了吗?我们之前有总结过 《浅谈javascript中的 “ && ” 和 “ || ” 》,"&&” 和 “||” 是逻辑运算表达式中的操作符。那么一个 “&” 或者一个 “|” 又代表什么含义呢?有什么特性呢?接下来,我们就来一一揭秘。

首先,我们得清楚 “&” 和 “|” 是位运算操作符。

位运算符用于在最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript中的所有数值都以IEEE-754 64位格式存储,但位操作符并不直接操作64位的值。而是先将64位的值转换成32位的整数,然后执行操作,最后再将结果转换为64位。对于开发人员来说,由于64位存储格式是透明的,因此整个过程就像是只存在32位的整数一样。

对于有符号的整数,32位中的前31位用于表示整数的值。第32位表示数值的符号:0表示正数,1表示负数。这个表示符号的位叫做符号位,符号位的值决定了其他位数值的格式。其中,正数以纯二进制格式存储,31位中的每一位都表示2的幂。第一位(叫做位0)表示20,第二位表示21,以此类推。没有用到的位以0表示,即忽略不计。例如,数值18的二进制表示是0000 0000 0000 0000 0000 0000 0001 0010,或者更简洁的10010。这是5个有效位,这5位本身就决定了实际的值。

负数同样以二进制码存储,但使用的格式是二进制补码。计算一个数值的二进制补码,需要经过下列3个步骤:

(1)求这个数值绝对值的二进制码(例如,要求-18的二进制补码,先求18的二进制码);

(2)求二进制反码,即将0替换为1,将1替换为0;

(3)得到的二进制反码加1。

这样,求得了-18的二进制表示,即1111 1111 1111 1111 1111 1111 1110 1110。

......在ECMAScript中,当对数值应用位操作符时,后台会发生如下转换过程:64位的数值被转换成32位数值,然后执行位操作,最后再将32位的结果转换回64位数值。这样,表面上看起来就好像是在操作32位数值,就跟在其他语言中以类似方式执行二进制操作一样。但这个转换过程也导致了一个严重的副效应,即在对特殊的NaN和Infinity值应用位操作时,这两个值都会被当成0来处理。

如果对非数值应用位操作符,会先使用Number()函数将该值转换为一个数值(自动完成),然后再应用位操作。得到的结果将是一个数值。 ......(截取自《Javascript高级程序设计》)

二、“&”(按位与AND):

按位与操作符由一个和号字符(&)表示,它有两个操作符数。从本质上来讲,按位与操作就是将两个数值的每一位对齐,对相同位置上的两个数执行AND操作。

按位与AND操作规则:只有两个数值的对应位都是1时才返回1,任何一位是0,结果都是0。

前面已经把理论性的东西说的太多了,但是我觉得理论又很有必要。接下来,直接分析例子吧!

我们先看上面题目中的 num1,num2,num3以及num6。我们尝试结合上面的理论来分析为什么会输出最终的结果。

// num1是1和0进行“按位与”操作后的返回值。1的二进制码简写为1,0的二进制码简写为0,根据上面的规则,第二个操作符数为0,结果是0
var num1 = 1 & 0;
console.log(num1); // 0 
// 第一个操作符数是字符串,按照前言里面的理论,对于非数值的操作符数,先使用Number()函数处理,结果返回NaN,NaN又会被当成0来处理。所以最终结果也是0
var num2 = 'string' & 1;
console.log(num2); // 0
// true是布尔类型值,同样使用Number()函数处理,处理后得到数值1,于是表达式就相当于“1 & 1” 进行位运算,当两个数值都为1的时候,结果返回1
var num3 = true & 1;
console.log(num3); // 1
// 23的二进制码是:...10111,5的二进制码是:...00101。然后每一位进行对齐处理,结合上面的规则,可以得出10111&00101的结果是:00101。00101就是5
var num6 = 23 & 5;
console.log(num6); // 5 
// 再加个例子:24的二进制码为...11000,7的二进制码为...00111,相同位置的两个数执行AND操作,结果发现结果是...00000。所以最终结果是0,你算对了吗?
var add1 = 24 & 7;
console.log(add1); // 0

三、“|”(按位或OR):

按位或操作符由一个竖线符号(|)表示,同样有两个操作符数。从本质上来讲,按位或操作也是将两个数值的每一位对齐,对相同位置上的两个数执行OR操作。

按位或OR操作规则:只要两个数值的对应位有一个是1就返回1,而只有在两个位都是0的情况下才返回0。

我们接最上面的例子来看吧!

// 第一个操作符数为undefined,第二个操作符数是false,均不是数值,所以都要先使用Number()函数处理,处理结果都是返回NaN,NaN又会被当成0处理,于是最终结果是0
var num4 = undefined | false;
console.log(num4); // 0
// 第一个操作符数相当于0,第二个操作符数相当于1,结合按位或的规则,最终结果是1
var num5 = undefined | true;
console.log(num5); // 1
// 23的二进制码是:...10111,5的二进制码是:...00101。然后每一位进行对齐处理,结合上面的规则,可以得出10111|00101的结果是:10111。10111就是23
var num7 = 23 | 5;
console.log(num7); // 23
// 再加个例子:24的二进制码为...11000,7的二进制码为...00111,相同位置的两个数执行AND操作,结果发现结果是...11111。所以最终结果是31,你算对了吗?
var add2 = 24 | 7;
console.log(add2); // 31

四、其他:

相信也会有一些朋友不知道怎么把数值转换成标准的二进制码,那么有没有快速的方法呢?答案是肯定的。

我的网上随机找到了一个在线转换工具地址:数值进制转换(点我查看)。(当然,你也可以使用你找到的别的工具,不管怎样,能实现效果就是我们的最终目的)

最后,再附上我通过手写转换二进制过程中总结的规律图,依然可以快速将数值转换成二进制码,逼格满满哒!

Javascript中的 “&” 和 “|” 详解

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
Array对象方法参考
Oct 03 Javascript
wordpress之js库集合研究介绍
Aug 17 Javascript
JavaScript Distilled 基础知识与函数
Apr 07 Javascript
javaScript(JS)替换节点实现思路介绍
Apr 17 Javascript
经过绑定元素时会多次触发mouseover和mouseout事件
Feb 28 Javascript
jquery 删除节点 添加节点 找兄弟节点的简单实现
Dec 07 Javascript
JavaScript设置名字输入不合法的实现方法
May 23 Javascript
JS+Ajax实现百度智能搜索框
Aug 04 Javascript
解决bootstrap中下拉菜单点击后不关闭的问题
Aug 10 Javascript
vue实现商品加减计算总价的实例代码
Aug 12 Javascript
javascript随机变色实例代码
Oct 15 Javascript
微信小程序使用前置摄像头拍照
Oct 22 Javascript
javascript实现简易计算器
Feb 01 #Javascript
javascript实现右下角广告框效果
Feb 01 #Javascript
基于javascript实现最简单选项卡切换
Feb 01 #Javascript
快速实现jQuery多级菜单效果
Feb 01 #Javascript
angular实现商品筛选功能
Feb 01 #Javascript
Bootstarp基本模版学习教程
Feb 01 #Javascript
angular实现表单验证及提交功能
Feb 01 #Javascript
You might like
php小偷相关截取函数备忘
2010/11/28 PHP
PHP中文处理 中文字符串截取(mb_substr)和获取中文字符串字数
2011/11/10 PHP
用PHP实现小写金额转换大写金额的代码(精确到分)
2012/01/10 PHP
封装ThinkPHP的一个文件上传方法实例
2014/10/31 PHP
PHP中使用CURL获取页面title例子
2015/01/07 PHP
Zend Guard使用指南及问题处理
2015/01/07 PHP
PHP解析RSS的方法
2015/03/05 PHP
Zend Framework教程之Zend_Db_Table表关联实例详解
2016/03/23 PHP
把textarea中字符串里含有的回车换行替换成<br>的javascript代码
2007/04/20 Javascript
JavaScript 未结束的字符串常量常见解决方法
2010/01/24 Javascript
利用js实现选项卡的特别效果的实例
2013/03/03 Javascript
利用浏览器全屏api实现js全屏
2014/01/16 Javascript
javascript 定时器工作原理分析
2016/12/03 Javascript
浅谈js for循环输出i为同一值的问题
2017/03/01 Javascript
JSONP跨域请求
2017/03/02 Javascript
webpack4 处理SCSS的方法示例
2018/09/03 Javascript
vue+axios实现文件下载及vue中使用axios的实例
2018/09/21 Javascript
Nodejs中的require函数的具体使用方法
2019/04/02 NodeJs
vue--vuex详解
2019/04/15 Javascript
[47:50]Secret vs VP 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
[48:31]完美世界DOTA2联赛PWL S3 DLG vs Phoenix 第二场 12.17
2020/12/19 DOTA
Python入门篇之条件、循环
2014/10/17 Python
python获取代理IP的实例分享
2018/05/07 Python
简单了解python数组的基本操作
2019/11/26 Python
python实现图像拼接功能
2020/03/23 Python
pytorch查看通道数 维数 尺寸大小方式
2020/05/26 Python
利用SVG和CSS3来实现一个炫酷的边框动画
2015/07/22 HTML / CSS
详解CSS3新增的背景属性
2019/12/25 HTML / CSS
美国设计师精美珠宝购物网:Netaya
2016/08/28 全球购物
为世界各地的女性设计和生产时尚服装:ROMWE
2016/09/17 全球购物
酒店采购员岗位职责
2014/03/14 职场文书
纪检监察建议书
2014/05/19 职场文书
2015年实习生工作总结报告
2015/04/28 职场文书
会议承办单位欢迎词
2015/09/30 职场文书
Redis5之后版本的高可用集群搭建的实现
2021/04/27 Redis
Android中View.post和Handler.post的关系
2022/06/05 Java/Android