提问人:Kenneth J 提问时间:12/1/2009 最后编辑:Jon SeigelKenneth J 更新时间:2/9/2023 访问量:41309
什么是 JavaScript >>>运算符,如何使用它?
What is the JavaScript >>> operator and how do you use it?
问:
我正在查看Mozilla的代码,这些代码为Array添加了过滤方法,其中有一行代码让我感到困惑。
var len = this.length >>> 0;
我以前从未见过>>>在 JavaScript 中使用。
它是什么,它有什么作用?
答:
即无符号右位移运算符。这与有符号的右位移位运算符之间的区别在于,无符号的右位移运算符 (>>>) 从左边填充零,而有符号的右位移位运算符 (>>) 填充符号位,从而在移位时保留数值的符号。
评论
>>>
+
Driis 已经充分解释了操作员是什么以及它的作用。以下是它背后的含义/为什么使用它:
将任何方向移动为 do 将返回原始数字,并将强制转换为 。您正在查看的示例代码似乎用于确保即使未定义也是数字。0
null
0
this.length >>> 0
len
this.length
对于许多人来说,按位操作是不清楚的(Douglas Crockford/jslint 建议不要使用这样的东西)。这并不意味着这样做是错误的,但存在更有利和熟悉的方法来使代码更具可读性。确保这一点的更明确的方法是以下两种方法之一。len
0
// 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;
评论
NaN
+{}
+length||0
它不仅将非数字转换为数字,还将它们转换为可以表示为 32 位无符号整数的数字。
虽然 JavaScript 的 Numbers 是双精度浮点数 (*),但按位运算符 (、 、 和 ) 是根据 32 位整数的运算来定义的。执行按位运算会将数字转换为 32 位有符号 int,在执行计算然后转换回 Number 之前,会丢失任何分数和高于 32 位的位数。<<
>>
&
|
~
因此,执行没有实际效果的按位运算,例如 0 位的右移,是四舍五入数字并确保其在 32 位 int 范围内的快速方法。此外,三元运算符在执行其无符号运算后,将其计算结果转换为无符号整数的 Number,而不是其他整数的有符号整数,因此它可用于将负数转换为 32 位 2 的补码版本作为大数。使用可确保整数介于 0 和 0xFFFFFFFF 之间。>>0
>>>
>>>0
在这种情况下,这很有用,因为 ECMAScript 根据 32 位无符号整数定义数组索引。因此,如果您尝试以完全复制 ECMAScript 第五版标准的方式实现,则可以像这样将数字转换为 32 位无符号 int。array.filter
实际上,这几乎没有实际必要,因为希望人们不会将 、 或 设置为 。array.length
0.5
-1
1e21
'LEMONS'
总结:
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 引擎实际上在可能的情况下使用 ints,我不会感到惊讶。但这将是一个你不会利用的实现细节。
评论
RangeError: invalid array length
Array.prototype.filter.call
array
Array
arguments
if
'lemons'>>>0 === 0 && 0 >>>0 === 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
因此,这里可能要做的是获取长度,如果长度未定义或不是整数,则为 0,如上面的示例所示。我认为在这种情况下,可以安全地假设永远不会.尽管如此,我认为这个例子是一个令人讨厌的黑客,原因有两个:"cabbage"
this.length
< 0
使用负数时的行为,在上面的示例中可能无意(或可能发生)副作用。
<<<
代码的意图并不明显,因为这个问题的存在验证了这一点。
最佳做法可能是使用更具可读性的内容,除非性能绝对关键:
isNaN(parseInt(foo)) ? 0 : parseInt(foo)
评论
-1 >>> 0
this.length
this.length
原因有二:
>>>的结果是“积分”
undefined >>> 0 = 0 (由于 JS 会尝试将 LFS 强制到数字上下文,这也适用于“foo”>>> 0 等)
请记住,JS 中的数字具有 double 的内部表示形式。 这只是一种“快速”的长度基本输入理智方式。
但是,-1 >>> 0(哎呀,可能不是所需的长度!
Mozilla 的所有 array extra 方法实现中使用了无符号右移运算符,以确保该属性是无符号的 32 位整数。length
数组对象的属性在规范中描述为:length
每个 Array 对象都有一个 length 属性,其值始终是小于 232 的非负整数。
此运算符是实现它的最短方法,内部数组方法使用 ToUint32
操作,但该方法不可访问,并且存在于规范中以实现目的。
Mozilla array extras 实现尝试与 ECMAScript 5 兼容,请查看该方法的描述 (§ 15.4.4.14):Array.prototype.indexOf
1. Let O be the result of calling ToObject passing the this value as the argument. 2. Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length". 3. Let len be ToUint32(lenValue). ....
正如你所看到的,他们只是想在 ES3 实现上重现该方法的行为以符合 ES5 规范,正如我之前所说,无符号右移运算符是最简单的方法。ToUint32
评论
ToUint32
Put
]] 内部方法,并且当对属性进行赋值时,会再次转换并执行其他操作,例如删除高于新长度的索引......Array.prototype
Array.prototype.indexOf.call({0:'foo', 1:'bar', length: 2}, 'bar') == 1;
arguments
length
length
ToUint32
下面的示例 Java 代码很好地解释了:
int x = 64;
System.out.println("x >>> 3 = " + (x >>> 3));
System.out.println("x >> 3 = " + (x >> 3));
System.out.println(Integer.toBinaryString(x >>> 3));
System.out.println(Integer.toBinaryString(x >> 3));
输出如下:
x >>> 3 = 536870904
x >> 3 = -8
11111111111111111111111111000
11111111111111111111111111111000
上一个:猴子修补@property
评论
Array.prototype.push
Array.prototype.pop