当前位置:  开发笔记 > 编程语言 > 正文

什么是JavaScript >>>运算符以及如何使用它?

如何解决《什么是JavaScript>>>运算符以及如何使用它?》经验,为你挑选了6个好方法。

我正在查看Mozilla的代码,它为Array添加了一个过滤方法,它有一行代码让我很困惑.

var len = this.length >>> 0;

我以前从未见过用于JavaScript的>>>.
它是什么,它做了什么?



1> bobince..:

它不只是将非Numbers转换为Number,而是将它们转换为可以表示为32位无符号整数的Numbers.

虽然JavaScript的数字是双精度浮点(*),位运算符(<<,>>,&,|~)在对32位整数运算的定义.在执行计算然后转换回Number之前,执行按位运算会将数字转换为32位signed int,丢失任何分数和高于32的位数.

因此,在没有实际效果的情况下执行按位操作(如向右移位0位>>0)是一种快速的方法来舍入数字并确保它在32位int范围内.此外,三元>>>运算符在执行无符号运算后,将其计算结果转换为无符号整数,而不是其他有符号整数,因此可将其用于将负数转换为32位二进制补码版本为大号.使用>>>0确保您有一个0到0xFFFFFFFF之间的整数.

在这种情况下,这很有用,因为ECMAScript根据32位无符号整数定义了数组索引.因此,如果您尝试以array.filter完全复制ECMAScript第五版标准所述的方式实现,则可以将数字转换为32位无符号整数.

(在现实中几乎没有实际的需要这是希望的人是不会被设置array.length0.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引擎实际上使用了它就不会让我感到惊讶.但这将是一个你不会接受任何实现细节的实现细节.优点.)


'array.length = LEMONS`的+1.必须找到一个非常烦人的人才能在他们的代码上玩这个技巧:3
但是,规范故意允许在非数组上调用许多Array函数(例如,通过`Array.prototype.filter.call`),因此`array`实际上可能不是真正的`Array`:它可能是其他的用户定义的类.(不幸的是,它不能可靠地成为NodeList,这是你真正想要的时候,因为它是一个宿主对象.这使你唯一真实地做这个`arguments`伪数组. )
深度说明和表格中的+2,为-1,因为array.length会自我验证,并且不能任意设置为非整数或0的值(FF会引发此错误:`RangeError:无效的数组长度')。

2> CMS..:

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

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

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

此运算符是实现它的最短方法,内部数组方法使用该ToUint32操作,但该方法无法访问并存在于规范中以用于实现目的.

Mozilla 阵列附加实现尝试符合ECMAScript 5,请查看Array.prototype.indexOf方法的描述(第15.4.4.14节):

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).
....

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


@Marcel:请记住,大多数`Array.prototype`方法都是*故意通用的*,它们可用于*类数组*对象,例如`Array.prototype.indexOf.call({0:'foo', 1:'bar',长度:2},'bar')== 1;`.`arguments`对象也是一个很好的例子.对于*pure*数组对象,不可能改变`length`属性的类型,因为它们实现了一个特殊的[[[`Put`](http://bit.ly/d5hfSL)]]内部方法,当对`length`属性进行赋值,再次转换为`ToUint32`并执行其他操作,如删除新长度以上的索引...
数组的长度是*可能是*不是整数吗?我无法想象,所以这种"ToUint32"对我来说似乎有点不必要了.

3> driis..:

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


@Ivan,通常情况下,我会说将值移动到零位置绝对没有意义.但这是Javascript,所以它背后可能有一个含义.我不是Javascript专家,但它可能是一种确保该值实际上是无类型Javasacript语言中的整数的方法.
`this.length >>> 0;`代码有意义吗?
@Ivan,见下面贾斯汀的回答.实际上,这是一种确保len变量包含数字的方法.

4> Justin Johns..:

Driis已经充分解释了操作员是什么以及它做了什么.这是它背后的意义/为什么使用它:

移动任何方向0确实返回原始数字并将转换null0.您正在查看的示例代码似乎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; 



5> fmark..:

>>>无符号右移运算符(参见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"的情况,如果是这样,是否真的需要将其转移到4294967295?看起来这样会导致循环运行的次数超过必要的次数.

6> 小智..:

两个原因:

    >>>的结果是"积分"

    undefined >>> 0 = 0(因为JS会尝试将LFS强制转换为数字上下文,这也适用于"foo">>> 0等)

请记住,JS中的数字具有double的内部表示.它只是一种基本输入理智的"快速"方式.

但是,-1 >>> 0(oops,可能不是所需的长度!)

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有