js的位操作

今天在看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运算的结果是一样的,都是将其转换成整数的一个运算。

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

推荐阅读更多精彩内容

  • 进制基本概念 什么是进制?进制是一种计数的方式,数值的表示形式 常见的进制十进制、二进制、八进制、十六进制 进制书...
    极客江南阅读 2,001评论 0 11
  • 1 关键字 1.1 关键字的概述 Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或...
    哈哈哎呦喂阅读 646评论 0 0
  • 一、ECMAScript 一元运算符 一元运算符只有一个参数,即要操作的对象或值。它们是 ECMAScript 中...
    耦耦阅读 525评论 0 0
  • 运算符是处理数据的基本方法,用来从现有的值得到新的值。JavaScript 提供了多种运算符,本章逐一介绍这些运算...
    徵羽kid阅读 671评论 0 0
  • vue渐进式框架 如果采用原生js来对dom元素进行操作,需要获取元素再获取相关内容然后添加一系列事件,这样操作繁...
    Sune小叶子阅读 6,719评论 1 2