什么是JavaScript>&燃气轮机&燃气轮机;操作员和您如何使用它?
我在看Mozilla的代码,它在数组中添加了一个过滤方法,它有一行代码让我感到困惑什么是JavaScript>&燃气轮机&燃气轮机;操作员和您如何使用它?,javascript,operators,bit-shift,Javascript,Operators,Bit Shift,我在看Mozilla的代码,它在数组中添加了一个过滤方法,它有一行代码让我感到困惑 var len = this.length >>> 0; 我以前从未见过在JavaScript中使用>>>它是什么,它做什么?那是操作员。这与之间的区别在于,无符号的右位移位运算符(>)从左开始填充零,有符号的右位移位运算符(>)填充符号位,因此,移位时保留数值的符号。充分解释了运算符是什么及其作用。下面是它背后的含义/使用原因: 按0移动任何方向都会返回原始数字,并将null转换为0。您正在
var len = this.length >>> 0;
我以前从未见过在JavaScript中使用>>>它是什么,它做什么?那是操作员。这与之间的区别在于,无符号的右位移位运算符(>)从左开始填充零,有符号的右位移位运算符(>)填充符号位,因此,移位时保留数值的符号。充分解释了运算符是什么及其作用。下面是它背后的含义/使用原因: 按
0
移动任何方向都会返回原始数字,并将null
转换为0
。您正在查看的示例代码似乎是使用this.length>>0
来确保len
是数字的,即使未定义this.length
对许多人来说,按位操作是不清楚的(道格拉斯·克罗克福德/jslint建议不要使用这种东西)。这并不意味着这样做是错误的,但存在更有利和更熟悉的方法来提高代码的可读性。确保len
为0
的更明确方法是以下两种方法之一
// Cast this.length to a number
var len = +this.length;
或
它不仅将非数字转换为数字,还将它们转换为可以表示为32位无符号整数的数字 尽管JavaScript的数字是双精度浮点(*),但按位运算符(
、&
、|
和~
)是根据对32位整数的运算定义的。执行逐位操作将数字转换为32位有符号整数,在执行计算之前,会丢失任何分数和高于32位的位,然后再转换回数字
因此,在没有实际效果的情况下执行按位操作,例如0位的右移>0
,是一种对数字进行四舍五入并确保其在32位整数范围内的快速方法。此外,三重>>
运算符在执行无符号运算后,将其计算结果转换为无符号整数,而不是其他运算符所做的有符号整数,因此可以使用它将负数转换为32位二补形式的大数。使用>>0
可以确保得到一个介于0和0xFFFFFF之间的整数
在这种情况下,这很有用,因为ECMAScript根据32位无符号整数定义数组索引。因此,如果您试图以与ECMAScript第五版标准完全相同的方式实现array.filter
,则可以将数字转换为32位无符号整数,如下所示
(实际上,这几乎没有实际需要,因为希望人们不会将array.length
设置为0.5
,-1
,1e21
或'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引擎在可能的情况下实际使用Int,我不会感到惊讶。但这将是一个您无法利用的实现细节。)
>
是无符号右移运算符(),与>
相反,签名的右移运算符
>>
更改负数移位的结果,因为它在移位时不保留符号位。这一点的后果可以通过解释者的例子来理解:
$ 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,如上面的“coball”
示例所示。我认为在这种情况下,可以安全地假设this.length
永远不会是<0
。然而,我认为这个例子是一个令人讨厌的黑客行为,原因有两个:
的行为有两个原因:
>>>的结果是一个“积分”
未定义的>>>0=0(因为JS将尝试将LFS强制为数字上下文,这也适用于“foo”>>0等)
请记住,JS中的数字内部表示为double。
这只是一种“快速”输入长度的基本方法
但是,-1>>>0(oops,可能不是所需的长度!)在Mozilla的所有array extra方法实现中使用无符号右移运算符,以确保length
属性是无符号32位整数
数组对象的length
属性在规范中如下所示:
每个数组对象都有一个长度属性,其值总是小于232的非负整数
此运算符是实现此操作的最短方法,内部数组方法使用此操作,但该方法不可访问,并且出于实现目的而存在于规范中
Mozilla array extras实现试图做到兼容,请查看array.prototype.indexOf
方法(§15.4.4.14)的描述:
1.让O作为通过此值调用ToObject的结果
作为论据。
2.让lenValue作为调用O的[[Get]]内部方法的结果
参数“长度”。
3.设len为ToUint32(lenValue)。
....
如您所见,他们只是想重现ToUint32
方法的行为,以符合ES3实现上的ES5规范,正如我前面所说的,这是最简单的方法。下面的示例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
伊万,这将使它移动0个位置;那句话不会改变任何事情。@Ivan,通常,我会说改变a值b
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).
....
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