资讯专栏INFORMATION COLUMN

js中表达式 >>> 0 浅析

Scliang / 778人阅读

摘要:向右被移出的位被丢弃,左侧用填充。因为符号位变成了,所以结果总是非负的。即便右移个比特,结果也是非负的。这些与移位的位数无关,移位位主要就是用了的内部特性做了前两种转换。一个小小的表达式,隐藏着着多重的异常处理。

今天在看lodash的源码中slice这个函数实现的时候发现了里面有这么一行代码

length = start > end ? 0 : ((end - start) >>> 0)
start >>>= 0

当时就很疑惑,知道 >>是移位,那>>>又是什么鬼,还有移位0位又有什么意义呢,带着强烈的好奇心,我就去探究了一下 >>> 0它到底暗藏什么玄机。

>>>>>有什么不一样

查了MDN原来>>>是无符号右移,>>是有符号移位,
>>有符号移位:该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧

-9 >> 2
11111111111111111111111111110111  // -9 -> 11111111111111111111111111111101   // -3

>>>无符号移位:该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符号位变成了 0,所以结果总是非负的。(即便右移 0 个比特,结果也是非负的。

9 >>> 2
00000000000000000000000000001001   // 9 ->  00000000000000000000000000000010 // 2

根据文档说明即使移动0位也可以将一个负数变成正数,甚至也可以将一个小数变成整数,将未定义的值转换为0,那到底移动0位是什么意思。

移位0有什么意义

查过一些资料,其中stackoverflow里面有一个高票回答,里面有这么一句话

It doesn"t just convert non-Numbers to Number, it converts them to Numbers that can be expressed as 32-bit unsigned ints.

原来移位操作符在移位前做了两种转换,第一将不是number类型的数据转换为number,第二将number转换为无符号的32bit数据,也就是Uint32类型。这些与移位的位数无关,移位0位主要就是用了js的内部特性做了前两种转换。

Uint32类型是如何转换的

1 . 如果不能转换为Number,那就为0
2 . 如果为非整数,先转换为整数,参考公式sign(n) ⋅ floor(abs(n))

function ToInteger(x) {
    x = Number(x);
    return x < 0 ? Math.ceil(x) : Math.floor(x);
}

3 . 如果是正数,返回正数,如果是负数,返回负数 + 2的32次方

function modulo(a, b) {
    return a - Math.floor(a/b)*b;
}
function ToUint32(x) {
    return modulo(ToInteger(x), Math.pow(2, 32));
}

参考文章 Integers and shift operators in JavaScript

总结

x >>> 0本质上就是保证x有意义(为数字类型),且为正整数,在有效的数组范围内(0 ~ 0xFFFFFFFF),且在无意义的情况下缺省值为0。一个小小的表达式,隐藏着着多重的异常处理。js真是诡异啊。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94623.html

相关文章

  • JSswitch的四种写法示例

      JavaScript 的 switch 有四样写法,你都知道哪些?   JavaScript 的 switch 语句只有一种写法。其他的写法,if 分支写法可以算一种,switch 分支写法可以算第二种,第三种是使用策略模式,如果要把条件运算符也算上的话,嗯,刚好四种。  switch一般写法  switch 的写法一般来说是 switch 变量或表达式,case 常量,比如:一个百分制成绩,...

    3403771864 评论0 收藏0
  • 讲解vue parseHTML源码解析harsendcomment钩子函数

      我们现在要讲述的是当解析器遇到一个文本节点时会如何为文本节点创建元素描述对象,那又该作何处理。  parseHTML(template,{   chars:function(){   //...   },   //...   })  chars源码:   chars:functionchars(text){   if(!currentParent){   {   if(text===templ...

    3403771864 评论0 收藏0
  • 解析ES6变量赋值和基本数据类型

      let和const  let和const两者并不存在变量提升  这里要说明的是变量一定要在声明后使用,否则报错。  vara=[];   for(vari=0;i<10;i++){   a[i]=function(){   console.log(i);   };   }   a[6]();//10  变量i是var声明的,我们要知道这里在全局范围内都有效。我们要知道在每一次循环中,新的...

    3403771864 评论0 收藏0
  • Vue编译器AST抽象语法树源码分析

     直接进入核心现在说说baseCompile核心代码:  //`createCompilerCreator`allowscreatingcompilersthatusealternative   //parser/optimizer/codegen,e.gtheSSRoptimizingcompiler.   //Herewejustexportadefaultcompilerusingthede...

    3403771864 评论0 收藏0
  • JavaScript时间复杂度和空间复杂度

      前言  在JS是用来时间复杂度和空间复杂度,时间复杂度和空间复杂度是衡量一个算法是否优秀的标准,现在我们就来说手时间复杂度和空间复杂度。  时间复杂度和空间复杂度是衡量一个算法是否优秀的标准,通常我们比较两个算法时会用到以下两种方法:  预先估算:首先做出算法设计,在去估算这个算法所需的时间复杂度和空间复杂度,两者进行比较,择优。  事后统计:写一个可执行程序/脚本用来表达两个算法,交给计算机...

    3403771864 评论0 收藏0

发表评论

0条评论

Scliang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<