什么是JavaScript >>>操作符,你如何使用它?

我正在从Mozilla的代码中添加一个filter方法到arrays,它有一行代码混淆了我。

var len = this.length >>> 0; 

我从来没有见过>>>在JavaScript中使用过。
它是什么,它有什么作用?

它不仅将非数字转换为数字,还将它们转换为可以表示为32位无符号整数的数字。

尽pipeJavaScript的Numbers是双精度浮点数(*),但按位运算符( <<>>&|~ )是按照32位整数运算来定义的。 按位操作将数字转换为32位有符号整数,在进行计算之前丢失小于32的任何分数和高位,然后转换回数字。

所以做一个没有实际效果的按位操作,如向右移位0位>>0 ,是一个快速的方法来四舍五入一个数字,并确保它在32位int范围内。 此外,三重>>>运算符在进行无符号运算后,将其计算结果转换为无符号整数的数字,而不是其他人的有符号整数,因此可用于将负数转换为32位数字,作为一个大数字的补码版本。 使用>>>0确保你有一个0到0xFFFFFFFF的整数。

在这种情况下,这很有用,因为ECMAScript以32位无符号整数定义数组索引。 所以,如果你想以一种与ECMAScript第五版标准所说的完全相同的方式来实现array.filter ,那么你会把这个数字转换为32位的unsigned int。

(事实上​​,对此没有什么实际需要,希望人们不会将1e21设置为0.51e21'LEMONS' 。但这是我们正在讨论的JavaScript作者,所以你永远不知道。 ..)

概要:

 1>>>0 === 1 -1>>>0 === 0xFFFFFFFF -1>>0 === -1 1.7>>>0 === 1 0x100000002>>>0 === 2 1e21>>>0 === 0xDEA00000 1e21>>0 === -0x21600000 Infinity>>>0 === 0 NaN>>>0 === 0 null>>>0 === 0 '1'>>>0 === 1 'x'>>>0 === 0 Object>>>0 === 0 

(*:好吧,它们被定义为像浮动操作一样,如果某些JavaScript引擎实际上使用了整数,出于性能方面的原因,这并不会让我感到惊讶,但这将是一个实现细节,的好处。)

无符号右移运算符用于Mozilla的所有数组extra的方法实现中,以确保length属性是一个无符号的32位整数

数组对象的length属性在规范中描述如下:

每个Array对象都有一个长度属性,其值始终是一个小于2 32的非负整数。

这个操作符是实现它的最简单的方法,内部的数组方法使用ToUint32操作,但是这个方法在规范中是不可访问和存在的。

Mozilla 数组extras实现尝试符合ECMAScript 5 ,查看Array.prototype.indexOf方法的描述(第15.4.4.14节):

设O是调用ToObject传递这个值的结果 
   作为论据。
 2.让lenValue是调用O的[[Get]]内部方法的结果 
   参数“长度”。
让len成为ToUint32(lenValue) 。
 ....

正如你所看到的,他们只是想重现ToUint32方法的行为,以符合ES3实现中的ES5规范,正如我之前所说的, 无符号右移运算符是最简单的方法。

Driis已经充分解释了运营商是什么,它做了什么。 这是它背后的意义/为什么使用它:

将任何方向移动0将返回原始数字,并将null0 。 看来你正在看的示例代码是使用this.length >>> 0以确保len是数字,即使this.length未定义。

对于很多人来说,按位操作是不清楚的(Douglas Crockford / jslintbuild议不要使用这样的东西)。 这并不意味着它做错了,而是更有利和更熟悉的方法使代码更具可读性。 确保len0更清楚的方法是以下两种方法之一。

 // Cast this.length to a number var len = +this.length; 

要么

 // Cast this.length to a number, or use 0 if this.length is // NaN/undefined (evaluates to false) var len = +this.length || 0; 

这是无符号的右移位运算符。 这与有符号位右移位运算符的区别在于, 无符号右位移运算符( >>> )从左侧填充零,而带符号右位移运算符( >> )填充符号位,因此在移位时保留数值的符号。

>>>无符号右移运算符 ( 参见JavaScript 1.5规范的第76页 ),而不是符号右移运算符>>

>>>改变负数的移位结果,因为移位时不保留符号位 。 这个后果可以通过一个例子来理解:

 $ 1 >> 0 1 $ 0 >> 0 0 $ -1 >> 0 -1 $ 1 >>> 0 1 $ 0 >>> 0 0 $ -1 >>> 0 4294967295 $(-1 >>> 0).toString(16) "ffffffff" $ "cabbage" >>> 0 0 

所以这里可能要做的是获得长度,或者如果长度未定义或者不是整数,则按照上面的"cabbage"示例获得长度。 我认为在这种情况下,假设this.length将永远不会< 0 。 不过,我认为这个例子是一个讨厌的黑客 ,原因有两个:

  1. 在使用负数时<<<的行为,在上面的例子中可能不会有意(或可能发生)的副作用。

  2. 代码的意图不明显 ,因为这个问题的存在被证实。

最佳做法可能是使用更可读的东西,除非性能是绝对重要的:

 isNaN(parseInt(foo)) ? 0 : parseInt(foo) 

两个原因:

  1. >>>的结果是一个“积分”

  2. 未定义>>> 0 = 0(因为JS会试图强制LFS到数字上下文,这也适用于“foo”>>> 0等)

请记住,JS中的数字具有double的内部表示。 这只是一个基本的input健全的“快速”方式。

然而 ,-1 >>> 0(哎呀,可能不是所需的长度!)