Javascript中的 “&” 和 “|” 你知多少?
一、前言:
在文章开始之前,先出几个题目给大家看看:
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中知而不全的this (转)
原文引自:http://www.cnblogs.com/snandy/p/4773184.html 都说 JavaScript 是一种很灵活的语言,这其实也可以说它是一个混乱的语言.它把函数式编程和面 ...
- JavaScript中typeof知多少?
typeof运算符介 绍:typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型.它返回值是一个字符串,该字符串说明运算数的类型. 你 知道下面typeof运算的结果吗? typeof ...
- JavaScript 中 typeof 知多少?
typeof运算符介绍:typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型.它返回值是一个字符串,该字符串说明运算数的类型. 你知道下面typeof运算的结果吗? typeof(1 ...
- Javascript中的数据类型知多少
JavaScript 是一种弱类型或者说动态语言.这意味着你不用提前声明变量的类型,在程序运行过程中,类型会被自动确定.这也意味着你可以使用同一个变量保存不同类型的数据 根据ECMAScript 5. ...
- JavaScript中的this陷阱的最全收集
JavaScript来自一门健全的语言,所以你可能觉得JavaScript中的this和其他面向对象的语言如java的this一样,是指存储在实例属性中的值.事实并非如此,在JavaScript中,最 ...
- JavaScript中的this陷阱的最全收集 没有之一
当有人问起你JavaScript有什么特点的时候,你可能立马就想到了单线程.事件驱动.面向对象等一堆词语,但是如果真的让你解释一下这些概 念,可能真解释不清楚.有句话这么说:如果你不能向一个6岁小孩解 ...
- 理解JavaScript中的作用域和上下文
JavaScript对于作用域(Scope)和上下文(Context)的实现是这门语言的一个非常独到的地方,部分归功于其独特的灵活性. 函数可以接收不同的的上下文和作用域.这些概念为JavaScrip ...
- javascript中的对象,原型,原型链和面向对象
一.javascript中的属性.方法 1.首先,关于javascript中的函数/“方法”,说明两点: 1)如果访问的对象属性是一个函数,有些开发者容易认为该函数属于这个对象,因此把“属性访问”叫做 ...
- 深入了解 JavaScript 中的 for 循环
在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是: 简单for循环 for-in forEach 在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循 ...
随机推荐
- flexpaper二次开发
1.首先下载FlexPaper的源码.下载地址 2.本人不懂flash,只是百度下,然后自己瞎弄弄的.我用的flash build 4.5 提供个key:1499-4181-9296-6452-299 ...
- Android非常实用的开源项目框架
我将文章中所描述的项目都集成在一个apk中,可以直接运行查看效果,2.2以上的机器都可以运行.因为不让直接上传apk文件,我压缩成了zip包 1. Universal-Image-Loader 实现异 ...
- 将UTF8编码转化为中文 - NSString方法
方法一: 代码如下,如有更好的方法 麻烦贴出来,这个方法是通过webview进行解码的 UIWebView *web = [[UIWebView alloc] init]; NSString *tsw ...
- ymodem协议c实现(转)
源:ymodem协议c实现 /****************************************Copyright (c)******************************** ...
- iOS强制切换横屏、竖屏
切换横竖屏最直接的方式是调用device的setOrientation方法.但是从sdk3.0以后,这个方法转为似有API,如果要上AppStore的话,要慎用! if ([[UIDevice cur ...
- Less-css预处理编译
node编译 第一步:https://nodejs.org/en/ 到node官网下载最新的node 第二步:和普通软件一样把node安装好 第三步:运行-cmd,准备安装less 全局安装(整个电 ...
- ios页面跳转
reference:http://blog.csdn.net/engandend/article/details/11706323 目前,就我所学到的内容,页面跳转有三种方法 一.直接推到下一个页面 ...
- WebForm和MVC中都可以使用的路由
1.在global.asax void Application_Start(object sender, EventArgs e) { // 在应用程序启动时运行的代码 // RouteConfig. ...
- UVa 299 - Train Swapping
题目大意:给n个数的一个序列,通过交换相邻的两个数使得这n个数按照从小到大的顺序排列. Inversion index problem: count how many swaps are needed ...
- django学习——url的name
html中的地址可以用写死的,也可以用生成的,如:<a href="{% url 'app-url' param1 param2 ... %}">link</a& ...