Hack convert javascript number to UInt32

Edit: This question has been deprecated since the Polyfill example has been updated. I leave the question here for reference only. Read the correct answer for useful information about the bitwise shift operator.


Question:

On line 7 in the Polyfill example of the Mozilla Array.prototype.indexOf page, they comment on this:

var length = this.length >>> 0; // Hack to convert object.length to a UInt32 

But the Mozilla bitwise shift specification clearly states that the operator returns a value of the same type as the left operand:

The shift operators convert their operands to thirty-two bit integers and return the result of the same type as the left operand.

So shouldn't the length get the standard 64-bit float value? Or can someone tell me where the hack begins?

+6
source share
3 answers

The ECMAScript specification states that the value is converted to UInt32 in steps 5 and 8 of http://www.ecma-international.org/ecma-262/5.1/#sec-11.7 :

11.7.3 Unsigned shift operator (→>)

Performs a bitwise zero-shift operation in the left operand with the value> specified by the right operand.

The product of ShiftExpression : ShiftExpression >>> AdditiveExpression is evaluated as follows:

  • Let lref be the result of evaluating ShiftExpression .
  • Let lval be GetValue(lref) .
  • Let rref be the result of evaluating AdditiveExpression .
  • Let rval be GetValue(rref) .
  • Let lnum be ToUint32(lval) .
  • Let rnum be ToUint32(rval) .
  • Let shiftCount be the result of masking all but the least significant 5 bits of rnum , i.e. the calculation of rnum & 0x1F .
  • Returns the result of performing zero fill of the shift lnum on shiftCount . Running bits are filled with zero. The result is a 32-bit unsigned integer .
+7
source

The result, in fact, is converted back to a number, that is, a floating point number with an accuracy of 64 bits. However, before it is converted back, both operands are converted to UInt32 , then the right shift operation is performed. This is indicated in ECMAScript here: http://www.ecma-international.org/ecma-262/5.1/#sec-11.7.3

So the final result of length >>> 0 is that >>> 0 itself is no-op, for converting length to UInt32 and then back to double. What is this for? This leads to a loss of accuracy and effectively causes the value to be 1) both integer and 2) in the range [0, 2 ^ 32-1]. For example, if it is -1, it will become 2 ^ 32-1 == 4294967295. If it was, 3.6, it will become 3.

+2
source

If you run this test, Math.floor will do the same. These hacks should be avoided if you want to understand your own code in a month or so.

 var a=3.6, b = a >>> 0; console.log(b); console.log(Math.floor(a)); 
0
source

All Articles