views:

540

answers:

3

I was looking at code from Mozilla that add a filter method to Array and it had a line of code that confused me.

var len = this.length >>> 0;

I have never seen >>> used in JavaScript before.
What is it and what does it do?

+13  A: 

That is the unsigned right bit shift operator. The difference between this and the signed right bit shift operator, is that the unsigned right bit shift operator (>>>) fills with zeroes from the left, and the signed right bit shift operator (>>) fills with the sign bit, thus preserving the sign of the numerical value when shifted.

driis
Does `this.length >>> 0;` code make sense?
Ivan Nevostruev
Ivan, that would shift it by 0 places; that statement wouldn't change anything.
Dean J
@Ivan, normally, I would say that shifting a value by zero places makes absolutely no sense. But this is Javascript, so there might be a meaning behind it. I am not a Javascript guru, but it might be a way to ensure that the value is in fact an integer in the typeless Javasacript language.
driis
@Ivan, see Justin's answer below. It is in fact a way to ensure that the len variable contains a number.
driis
so is the unary `+` operator
barkmadley
+13  A: 

Driis has sufficiently explained what the operator is and what it does. Here's the meaning behind it/why it was used:

Shifting any direction by 0 does returns the original number and will cast null to 0. It seems that the example code that you are looking at is using this.length >>> 0 to ensure that len is numeric even if this.length is not defined.

For many people, bitwise operations are unclear (and Douglas Crockford/jslint suggests against using such things). It doesn't mean that its wrong to do, but more favorable and familiar methods exist to make code more readable. A more clear way to ensure that len is 0 is either of the following two methods.

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

or

// Cast this.length to a number, or use 0 if this.length is
// NaN/undefined (evaluates to false)
var len = +this.length || 0;
Justin Johnson
+1 for a nice clear answer :)
fudgey
Although, your second solution would sometimes evaluate to `NaN`.. E.g. `+{}` ... It's probably best to combine the two: `+length||0`
J-P
this.length is in the context of the array object, which cannot be anything besides a non-negative integer (at least in FF), so it is not a possibility here. Also, {} || 1 returns {} so you are no better off if this.length is an object. The benefit to also unary casting this.length in the first method is that it handles cases where this.length is NaN. Edited response to reflect that.
Justin Johnson
jslint would complain about var len = +this.length too as "confusing plusses". Douglas, you so picky!
Bayard Randel
Douglas is picky. And while his arguments are wise and typically well founded, what he says is not absolute nor gospel.
Justin Johnson
+15  A: 

It doesn't just convert non-Numbers to Number, it converts them to Numbers that can be expressed as 32-bit unsigned ints.

Although JavaScript's Numbers are double-precision floats(*), the bitwise operators (<<, >>, &, | and ~) are defined in terms of operations on 32-bit integers. Doing a bitwise operation converts the number to a 32-bit signed int, losing any fractions and higher-place bits than 32, before doing the calculation and then converting back to Number.

So doing a bitwise operation with no actual effect, like a rightward-shift of 0 bits >>0, is a quick way to round a number and ensure it is in the 32-bit int range. Additionally, the triple >>> operator, after doing its unsigned operation, converts the results of its calculation to Number as an unsigned integer rather than the signed integer the others do, so it can be used to convert negatives to the 32-bit-two's-complement version as a large Number. Using >>>0 ensures you've got an integer between 0 and 0xFFFFFFFF.

In this case this is useful because ECMAScript defines Array indexes in terms of 32 bit unsigned ints. So if you're trying to implement array.filter in a way that exactly duplicates what the ECMAScript Fifth Edition standard says, you would cast the number to 32-bit unsigned int like this.

(In reality there's little practical need for this as hopefully people aren't going to be setting array.length to 0.5, -1, 1e21 or 'LEMONS'. But this is JavaScript authors we're talking about, so you never know...)

Summary:

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

(*: well, they're defined as behaving like floats. It wouldn't surprise me if some JavaScript engine actually used ints when it could, for performance reasons. But that would be an implementation detail you wouldn't get to take any advantage of.)

bobince
+2 in depth description and table, -1 because array.length validates itself and can't be arbitrarily set to anything that is not an integer or 0 (FF throws this error: `RangeError: invalid array length`).
Justin Johnson
However, the spec deliberately allows many Array functions to be called on non-Array (eg. via `Array.prototype.filter.call`), so `array` might not actually be a real `Array`: it might be some other user-defined class. (Unfortunately, it can't reliably be a NodeList, which is when you'd really want to do that, as that's a host object. That leaves the only place you'd realistically do that as the `arguments` pseudo-Array.)
bobince