user5047085
user5047085

Reputation:

What is the `>>>` operator in JavaScript?

I was looking at the polyfill for Array.prototype.map:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

if (!Array.prototype.map) {

  Array.prototype.map = function(callback/*, thisArg*/) {

    var T, A, k;

    if (this == null) {
      throw new TypeError('this is null or not defined');
    }

    // 1. Let O be the result of calling ToObject passing the |this| 
    //    value as the argument.
    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get internal 
    //    method of O with the argument "length".
    // 3. Let len be ToUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If IsCallable(callback) is false, throw a TypeError exception.
    // See: http://es5.github.com/#x9.11
    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' is not a function');
    }

    // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
    if (arguments.length > 1) {
      T = arguments[1];
    }

    // 6. Let A be a new array created as if by the expression new Array(len) 
    //    where Array is the standard built-in constructor with that name and 
    //    len is the value of len.
    A = new Array(len);

    // 7. Let k be 0
    k = 0;

    // 8. Repeat, while k < len
    while (k < len) {

      var kValue, mappedValue;

      // a. Let Pk be ToString(k).
      //   This is implicit for LHS operands of the in operator
      // b. Let kPresent be the result of calling the HasProperty internal 
      //    method of O with argument Pk.
      //   This step can be combined with c
      // c. If kPresent is true, then
      if (k in O) {

        // i. Let kValue be the result of calling the Get internal 
        //    method of O with argument Pk.
        kValue = O[k];

        // ii. Let mappedValue be the result of calling the Call internal 
        //     method of callback with T as the this value and argument 
        //     list containing kValue, k, and O.
        mappedValue = callback.call(T, kValue, k, O);

        // iii. Call the DefineOwnProperty internal method of A with arguments
        // Pk, Property Descriptor
        // { Value: mappedValue,
        //   Writable: true,
        //   Enumerable: true,
        //   Configurable: true },
        // and false.

        // In browsers that support Object.defineProperty, use the following:
        // Object.defineProperty(A, k, {
        //   value: mappedValue,
        //   writable: true,
        //   enumerable: true,
        //   configurable: true
        // });

        // For best browser support, use the following:
        A[k] = mappedValue;
      }
      // d. Increase k by 1.
      k++;
    }

    // 9. return A
    return A;
  };
}

Upvotes: 2

Views: 155

Answers (2)

Pointy
Pointy

Reputation: 413712

The real question is, "why is the polyfill doing that?" The answer is that the code is trying to mimic the "ecumenical" nature of the native .map() method. The native code will put up with any this object that looks like an array. To that end, the code checks to see if there's a .length property, and if there is it sets out to treat it as the length of what hopefully will be an array-like object. Because a real array always has an integer length value, this code coerces the .length property of whatever this references to an integer by using a do-nothing bitwise expression.

There are other do-nothing bitwise expressions that would usually work just as well:

var len = ~~ O.length;
var len = O.length | 0;

and so on. However, in the specific case of array lengths, the bitwise >>> operator is special in that it coerces to unsigned 32-bit values. If you've got an array-like object with more than 2 billion (plus a little more) entries, it makes a difference.

All of the JavaScript bitwise operators implicitly turn the floating-point number operands to 32-bit integers before doing their thing, so the result always reflects that even though len (the result of the expression) is still an ordinary JavaScript number (double-precision floating point).

Upvotes: 0

iPhoenix
iPhoenix

Reputation: 737

It is the zero-fill right shift operator.

According to Mozilla,

“This operator shifts the first operand the specified number of bits to the right. Excess bits shifted off to the right are discarded. Zero bits are shifted in from the left. The sign bit becomes 0, so the result is always non-negative.”

Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Unsigned_right_shift

Upvotes: 1

Related Questions