专栏首页狮乐园简单探索 js 中 something >> 0 的原理

简单探索 js 中 something >> 0 的原理

关于这个问题是今天改公司项目小程序的一个bug时看到的,修复这个bug的解决方法是需要引入 String.prototype.padStart 的 polyfill,所以我就顺带扫了一眼这个 polyfill 里面的实现是怎样的,结果发现这么一行:

// truncate if number or convert non-number to 0
target = target >> 0;

我倒不是对这个代码本身的作用有什么疑问,毕竟之前看过好多关于 js 技巧的文章,其中都介绍过这种写法,并且自己也在实际工作中运用过多次。无论之前看过它几次,写过它几次,都没有追究它的原理到底是什么。至于要说当时为什么没有追究,原因一方面是因为没有时间,另一方面是当时自己水平也比较差,什么 ECMAScript 标准根本无从看起啊。经过不懈努力,终于觉得自己可以看懂一些规范了,所以借这个机会来根据规范看看它的原理是什么。

关于这行代码具体使用了什么语法以及达到的效果我就不废话了。第一步,我们需要从规范的哪里看起呢?因为完整的规范很长,我们不可能从头看起。我们需要根据规范的目录和已知代码来定位我们需要查找的具体章节。根据上面的代码可以得知,其中的操作符是一个右移操作符,如果英语比较好的或者对计算机术语比较熟悉,可以很快联想到 right-shift 这个词语(如果不好也可以根据词典得知),然后应用一下搜索大法就好了,在规范中搜索 right-shirt 相关的内容,然后再目中录就可以定位到以下信息:

1.12.8.4 The Signed Right Shift Operator ( >> )

这就好办了,直接跳到 12.8.4 章节,估计要看的主要内容都在这个章节中了,瞬间缩小了查询范围。

跳转到这个章节以后,看一下描述,如下:

Performs a sign-filling bitwise right shift operation on the left operand by the amount specified by the right operand.

应该是没错了,继续往下看,可以发现 12.8.4.1 中详细介绍了右移操作符的相关规范。

大概流程可以简单理解为,分别求得右移操作符左右两侧表达式的值后(其中包含一些取值、校验、转换逻辑),之后按照右移逻辑返回一个32位有符号整数。关于代码,我们比较感兴趣的是操作符左侧所对应的取值逻辑,所以这里我们需要详细看关于操作符左侧取值的逻辑,相关的步骤包含 1、2、3、7、8,依次是:

  • 第一步很简单,就是将 ShiftExpression 求值,记作 lref
  • 第二步对 lref 求值,记作 lval,求值的过程参考 GetValue
  • 第三步根据 ReturnIfAbrupt 来判定 lval 是否是异常值
  • 第七步对 lval 进行转换,记作 lnum,转换的过程参考 ToInt32
  • 第八步根据 ReturnIfAbrupt 来判定 lnum 是否是异常值

光看这个步骤是没有任何用处的,所以还需要继续看一下规范中关于 GetValue 和 ToInt32 的章节,这次就不用搜索了,直接点击链接跳转过去即可。

GetValue 如下:

ToInt32 如下:

这两个方法的详细过程就不说明了,以一个简单的例子大概理一下流程,比如使用以上代码时,假设 target 的类型是字符串,比如:

var target = 'a'

target = target >> 0
console.log(target) // 0

根据 GetValue 的逻辑可以发现,走到第二步就返回该值了,因为它是一个基础数据类型,所以 lval 的值为 ‘a’。之后带入 ToInt32(‘a’) 根据流程第一步的说明,首先进行 ToNumber(‘a’),关于 ToNumber 的规范比较长,这里就不截图了,总之最后会返回 NaN。然后顺着流程往下走,到第三步就会发现,最终 ToInt32(‘a’) 会返回 +0。

之后带入之前右移操作规范的 10 和 11 步就会得知,’a’ >> 0 等价于 +0 >> 0,最终的结果是 +0。对于其他的情况,在测试的基础上并带入以上流程,马上就会得知其原因,这里就不赘述了。

最后想说的是,我认为对于这种颗粒度的知识没有必要专门投入时间去学习和掌握,因为太过细小和零碎。但是当我们遇到一些自己不懂或者不熟悉的东西时,一定要有意识去寻根问底,这样积少成多,精通 js 早晚会变成现实。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 高级 Angular 组件模式 (3a)

    针对第一个问题,我们使用@ContentChildren装饰器(因为它获取所有的子组件引用),但是它无法解决第二个问题。

    littlelyon
  • 高级 Vue 组件模式 (9)

    到此为止,我们的 toggle 组件已经足够强大以及好用了,因此这篇文章不会再为它增加新的特性。如果你是从第一篇文章一直读到这里的读者,你一定会发现,整篇文章中...

    littlelyon
  • 高级 Vue 组件模式 (4)

    在第三篇文章中,我们使用 mixin 来抽离了注入 toggle 依赖项的公共逻辑。在 react 中,类似的需求是通过 HOC 的方式来解决的,但是仔细想想的...

    littlelyon
  • 要搞懂大数据和人工智能的关系,先分清这两个概念

    AI起跑线原创文章 ? 海豚小号 欢迎关注 大数据和人工智能,是近年来无处不在的两个超级热词。 很多小伙伴只知道这两个概念都是IT领域的新科技,但不太清楚,它...

    企鹅号小编
  • MySQL数据备份与恢复

    常用source命令,用use进入到某个数据库,mysql>source D:\sys.sql,后面的参数为脚本文件

    Linux
  • Android开发笔记(一百二十九)使用变换图形

    ClipDrawable可设置图形的裁剪幅度,它的构造函数除了指定来源图形之外,还可以指定图形的裁剪方式(从开始裁剪还是从中间裁剪还是从末尾裁剪),以及裁剪...

    用户4464237
  • 黑客们会用到哪些Python技术?

    Python已经成为漏洞开发领域的行业标准,读者会发现大多数概念验证工具都是用Python语言编写的(除了用Ruby写的安全漏洞检测工具)。Python允许开发...

    小小詹同学
  • iOS 自定义相机页面

    我们今天先来说说第一种。也就是类似我文章头部的这种界面怎么画出来。额~这时候还是给心急的上个Demo吧。在文中,顺便说下我碰到的两个问题:拍摄页灰色透明遮罩绘制...

    Raindew
  • nginx实现图片防盗链-技术精短文

    前几天讲了《nginx下载防盗链》,今天继续说下图片防盗链. 他们两个使用的指令不同,前者使用secure link,并且需要程序配合,但是效果非常好;后者不需...

    后端技术探索
  • 算法模板——二分图匹配

    实现功能为二分图匹配 原理:匈牙利算法,核心思想——匹配上了就配,没直接匹配上也要通过前面的腾出位置让这个匹配上(详见:趣写算法系列之——匈牙利算法) 本程序以...

    HansBug

扫码关注云+社区

领取腾讯云代金券