位操作符

位操作符用于数值的底层操作,ECMAScript中的所有数值都一样64位格式存储,但位操作并不直接应用到64位表示,而是先把值转换为32位整数,再进行位操作,之后再把结果转换为64位,对于开发者而言,只需要考虑32位整数即可

有符号整数使用32位的前31位表示整数值,第32位表示数值的符号,0表示正,1表示负。这一位称为符号位,它的值决定了数值其余部分的格式

如何将二进制转为十进制

数值18的二进制格式为00000000000000000000000000010010,精简: 10010,后者是用到了5个有效位,决定了实际的值

image.png

负值以一种称为二补数(补码)的二进制编码存储,一个数值的二补数通过三个步骤计算得到:

  1. 确定绝对值的二进制表示(如:-18,先确定18的二进制表示)
  2. 找到数值的一补数(或反码),换句话说,就是每个0都变成1,每个1都变成
  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  1101
                      1 
---------------------------------------------- 
1111  1111  1111  1111  1111  1111  1110  1110 

那么结果:-18的二进制表示就是11111111111111111111111111101110

ECMAScript会帮我们记录这些信息,在把负值输出为一个二进制字符串时,我们会得到一个签名加了减号的绝对值

let num = -18;
console.log(num.toString(2)); // '-10010'

在将-18转换为二进制字符串时,结果得到-100,转换过程会求得二补数,然后再以更符合逻辑的形式表示出来

注意: 默认情况下,ECMAScript中的所有整数都表示为有符号数
但其实存在无符号整数,对于无符号整数来说,第32位不表示符号,因为只有正值,无符号整数比有符号整数的范围更大,因为符号位被用来表示数值

注意

特殊值: NaN、 Infinity 在位操作中都会被当成0处理
非数值: 首先隐式使用Number函数将该值转换为数值,然后应用位操作,最终结果为数值

按位非

按位非操作符使用波浪符 ~表示,它的作用是返回数值的一补数

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

由此可看出:按位非的最终效果是对数值取反并减1

按位与

按位与使用和号&表示,有两个操作数,本质上,按位与就是将两个数的每一个位对齐,然后基于真值表中的规则,对每一位执行相应的与操作

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

按位与操作在两个位都是1时返回1,在任何一位是0时返回0

栗子:对数值25与3 进行与操作

let result = 25 & 3;
console.log(result); // 1

计算过程:

  25 = 0000 0000 0000 0000 0000 0000 0001 1001
  3 =  0000 0000 0000 0000 0000 0000 0000 0011
 --------------------------------------------- 
 AND = 0000 0000 0000 0000 0000 0000 0000 0001

按位或

按位或操作符用管道符|表示,使用两个操作符,按位或遵循如下真值表

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

按位或操作在失少一位是1时返回1,两位都是0时返回0

栗子:

let result = 25 | 3;
console.log(result); // 27

在参与计算的两个数中,有 4位都是 1,因此它们直接对应到结果上。二进制码 11011等于 27

25 = 0000 0000 0000 0000 0000 0000 0001 1001    
 3 = 0000 0000 0000 0000 0000 0000 0000 0011 
---------------------------------------------  
OR = 0000 0000 0000 0000 0000 0000 0001 1011

按位异或

按位异或使用脱字符^表示,同样有两个操作符,真值表

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

按位异或与按位或的区别:它只在一位上是1的时候返回1(两位都是1或者0,则返回0)

栗子:

let result = 25 ^ 3
console.log(result); // 26
 25 = 0000 0000 0000 0000 0000 0000 0001 1001   
  3 = 0000 0000 0000 0000 0000 0000 0000 0011 
 --------------------------------------------- 
XOR = 0000 0000 0000 0000 0000 0000 0001 1010

注意:对于同样两个值:执行按位或与 比 执行按位或操作得到的结果小1

左移

左移操作符用两个小于号<<表示,会按照指定的位数将数值的所有位向左移动

例如:数值2(二进制10)向左移5位,就会得到64(二进制1000000)

let oValue = 2; // 等于二进制 10
let nValue = oValue << 5 // 等于二进制 100000,即十进制64

在移位后,数值右端会空出5位,左移会以0填充这些空位,让结果是完整的32位数值


image.png

注意:左移会保留它所操作数值的符号,比如:如果-2左移5位,将得到-64,而不是正64

有符号右移

有符号右移由两个大于号(>>)表示,会将数值的所有32位都想右移,同时保留符号(正或负)。有符号右移实际上是左移的逆运算

栗子:如果将64右移5位,那就是2

let oValue = 64; // 等于二进制 1000000
let nValue = 64 >> 5; // 等于二进制 10 即十进制2
image.png

位移后会出现空位,右移后的空位会出现在左侧,且在符号位之后,ECMAScript会用符号位的值来填充这些空位(即正数补零,负数补1), 以得到完整的数值

无符号右移

无符号右移用3个大于号表示>>>, 会将数值的所有32位都向右移动,对于正数,无符号右移与有符号右移结果相同

栗子:64向右移动5位,会变成2

let oValue = 64; // 等于二进制 1000000
let nValue = oldValue >>> 5; // 等于二进制 10 即十进制2

对于负数,无符号右移操作符将负数的二进制表示当成正数的二进制来表示处理,因为负数是其绝对值的二补数,所以右移之后结果变得非常大

let oValue = -64; // 等于二进制 11111111111111111111111111000000
let nValue = oValue >>> 5; // 等于十进制 134217726 

在对-64无符号右移5位后,结果是134 217 726,
这是因为-64的二进制表示:1111111111111111111 1111111000000
无符号右移却将它当成正值,也就是: 4 294 967 232
把这个值右移5位后,结果:00000111111111111111111111111110
即: 134 217 726

-- 来源<JavaScript高级程序设计第四版>

位运算符的用途

  1. 用于判断一个数的奇偶
// %
let num = 1;
let isEven = num % 2 === 0
// &
let isEvent = num & 0 === 0;  // 判断是否是偶像  位操作符比 % 要快
  1. 利用 ^ 完成值的交换
let a = 1,
     b= 2;

2.1 第一种: 使用temp

let temp = a;
a = b;
b = temp;

2.2 第二种: 使用解构

[a, b] = [b, a]

2.3 第三种:使用 ^

a ^= b
b ^= a
a ^= b
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容

  • 位操作符用于在最近本的层次上,即按内存中表示数值的位来操作数值。ECMAScript中的所有数值都以 IEEE-7...
    RocWang丶阅读 811评论 0 0
  • JavaScript位操作符 位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript...
    阿丶炳阅读 205评论 0 0
  • 位操作符用于再最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript中的所有数值都以IEEE-75...
    meiqiuyang阅读 347评论 0 0
  • 位运算用在最基本的层次,是直接用内存中的数值的位来操作数值。 js所有的数字都以IEEE-754 64位存储,但在...
    Naeco阅读 319评论 0 1
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,519评论 16 22