转自 https://segmentfault.com/q/1010000005697515
~ 运算符查看表达式的二进制表示形式的值,并执行位非运算。
Javascript 按位取反运算符 (~) ,对一个表达式执行位非(求非)运算。如 ~1 = -2; ~2 = -3;
按位取反大体流程是这样的:
就来看看~1
的计算步骤:
- 将
1
(这里叫:原码)转二进制 =00000001
- 按位取反 =
11111110
- 发现符号位(即最高位)为
1
(表示负数),将除符号位之外的其他数字取反 =10000001
- 末位加1取其补码 =
10000010
- 转换回十进制 =
-2
计算步骤就这么奇怪,讨厌,但就是有牛逼的人乐意这么写,让你看不懂代码,以此表示高深莫测,去吧少年,去揍他们^^
--------------------------------------------------------------------------------------------------------------------------------------------------------------
偶然看到这个问题,挖个坟。
按位取反的运算规则上面那位同学已经说的很好了,我补充三点:
- 按位取反的运算规则这么奇怪并不是JavaScript独有的,而是所有的计算机语言都是这样的。这样做的主要原因是为了为了统一减法和加法,在计算机中,减法会变成加一个负数,而负数会以补码的形式存储。而这样主要是因为补码和数字的十进制数有这么转换关系,负数:
补码(x) = -x - 1
,正数:补码(x) = x
- 因为补码是针对负数存在的,那么只要数据类型有
无符号数
,就没有这样的烦恼了,比如C语言有无符号整型,就能对无符号整型直接按位取反。 - 如果没有无符号类型,而且也只是想要按位取反,而不是附带补码的按位取反,需要另外的方法。让全1的数据和当前数据做按位抑或就行了。比如,你有一个32位的数据a,需要对它做按位取反,那么这样就行了:
0xFFFF ^ a
var a = 0x8321;
console.log(a.toString(2));
console.log((0xFFFF ^ a).toString(2));
//1000001100100001
//111110011011110 => 左边最高位是0,被隐藏了。