美文网首页
js的位操作

js的位操作

作者: coolcao | 来源:发表于2019-10-16 22:11 被阅读0次

今天在看js的Array的方法时, 看到源码中有下面的一段代码, 挺有意思, 是关于位运算的, 就拿来研究了一下:

var len = t.length >>> 0;

这里使用了 >>> ,无符号右移运算符, 还右移了 0 位, 初看有点蒙, 到底啥意思? 带着疑问做了如下实验:

console.log(1 >>> 0);               //1
console.log(1.1 >>> 0);             //1
console.log(NaN >>> 0);             //0
console.log(true >>> 0);            //1
console.log(false >>> 0);           //0
console.log('a' >>> 0);             //0
console.log('123' >>> 0);           //123
console.log('a123' >>> 0);          //0
console.log({} >>> 0);              //0
console.log(function() {} >>> 0);   //0
console.log(null >>> 0);            //0
console.log(undefined >>> 0);       //0

从结果来看,不管是什么类型的数据,都被强制转换成了整型。 为什么 >>> 运算符会如此呢?这要从js的位运算符说起。

位运算符

位运算符用于在最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript中的所有数值都以IEEE-745 64位格式存储,但 位操作符并不直接操作64位的值,而是将64位的值转换成32位的整数,然后执行操作,最后再将结果转换回64位。

对于有符号的整数,32位中的前31位表示整数的值,第32位表示整数的符号,0表示整数,1表示负数。这个表示符号的位叫做 符号位,符号位的值决定了其他位数值的格式。其中,整数以纯二进制格式存储,31位中的每一位都表示2的幂。负数同样以二进制存储,但使用的格式是二进制补码 计算一个数值的二进制补码,需要经过下列3个步骤: 1.求这个数值绝对值的二进制码 2.求二进制码的反码,即将0替换为1,1替换为0 3.得到的二进制反码加1

例如,要求-18的二进制码,首先求18的二进制码:

0000 0000 0000 0000 0000 0000 0001 0010

求其反码:

1111 1111 1111 1111 1111 1111 1110 1101

最后反码加1

1111 1111 1111 1111 1111 1111 1110 1110

这样就求得了-18的二进制表示。

如果对非数值应用位操作符,会显示用Number()函数将改数值转换成一个数值(自动完成),然后再用应位操作符。

按位非 ~

按位非的结果就是,返回数值的反码。

var num = 25;           //二进制 00000000000000000000000000011001
var num2 = ~num;        //二进制 11111111111111111111111111100110
console.log(num2);      //-26

这里,对25执行按位非操作,结果得到了-26.这也验证了按位非操作的实质:操作数的负值减1 。因此,下面的代码也能得到相同的结果:

var num = 25;
var num2 = -num - 1;
console.log(num2);

虽然以上代码也能返回同样的结果,但由于按位非是在数值表示的最底层执行操作,因此速度更快。

按位与 &

按位或 |

按位异或 ^

按位异或操作扶由一个插入符号(^)表示,也有两个操作数。以下是按位异或的真值表:

第一个数值的位 第二个数值的位 结果
1 1 0
1 0 1
0 1 1
0 0 0

左移 <<

将数值的所有位向左移动指定的位。 左移的结果是,移动n位,乘以2的n次幂。例如,2<<5 = 2*2^5 = 64

左移不会影响操作数的符号位。

有符号右移[算数右移] >>

符号位不移,其他位右移,在左端补k个最高有效位的值。

无符号右移[逻辑右移] >>>

这个操作符会将数值的所有32位都向右移动。对正数来说无符号右移的结果和有符号相同。但是对于负数来说,情况就不一样了。 无符号右移操作符会把负数的二进制码当成正数的二进制码,而且由于负数以其绝对值的二进制补码形式表示,因此会导致无符号右移后的结果非常之大。 例如,上面的例子中,-18的二进制码:

1111 1111 1111 1111 1111 1111 1110 1110

右移一位: -18 >>> 1

0111 1111 1111 1111 1111 1111 1111 0111

这时将这个二进制码转换成正数是:2147483639


好了,我们回过头来看最初在js源码中看到的关于>>>那个问题,任何类型的数值,经过无符号右移0位后都被强制转换成了整数。 因为,在右移之前,先使用Number()函数转换成数值类型,移动0位相当于没移,因此,无论何种类型的值,>>>0被强制转换成整数类型。 那么,问题来了,Number()进行转换的时候,有一些是不能转换为整数的,比如,Number('a')得到的是NaN,NaN的类型也是number类型,但是,他却不是一个确定的值,js在对NaN进行位运算时,将0作为 运算元。

所以,如果看透了位运算,你会发现,其实 a>>>0 其实和 ~~a运算的结果是一样的,都是将其转换成整数的一个运算。

相关文章

  • js的位操作

    今天在看js的Array的方法时, 看到源码中有下面的一段代码, 挺有意思, 是关于位运算的, 就拿来研究了一下:...

  • JS操作属性、JS换肤、JS操作style属性、JS操作clas

    JS操作属性: JS换肤: JS操作style属性: JS操作class: JS中括号操作属性: JS函数: JS...

  • JS-12day

    1、js操作style属性 2、js操作属性 3、js函数 4、js换肤 5、js换肤可控制 6、js中括号操作属...

  • JS属性

    JS操作style属性 JS操作class JS操作括号属性 var oDiv = document.getEle...

  • JS操作属性 定时器和函数

    JS操作style属性 JS操作class JS操作括号属性 var oDiv = document.getEle...

  • [JS] 有符号整数的位操作

    1. 32位有符号整数 按位操作符(Bitwise operators)会使用内置函数,7.1.5 ToInt32...

  • JS操作属性、函数

    条件运算符 运算符的优先级 代码块 JS操作属性 JS换肤 JS操作style属性 JS操作

  • 前端(十二)2

    1.代码块 2.js操作属性 3.js换肤 4.js操作style属性 5.js操作 6.js中括号操作属性 7....

  • JS按位操作符

    按位操作符(Bitwise operators) 将其操作数(operands)当作32位的比特序列(由0和1组成...

  • ~运算符

    这是js中的一元操作符:按位取反。 ~~true == 1~~false == 0~~"" == 0~~[] ==...

网友评论

      本文标题:js的位操作

      本文链接:https://www.haomeiwen.com/subject/pxjpmctx.html