Array Reduce Polyfill Explanation

安稳与你 提交于 2019-12-05 01:18:37

问题


Apologize in advance for lengthy post. I am trying to understand array reduce polyfill provided by MDN. I could not understand some lines in the polyfill can you explain it please. Below is the code

    if (!Array.prototype.reduce) {
      Object.defineProperty(Array.prototype, 'reduce', {
        value: function(callback /*, initialValue*/) {
          if (this === null) {
            throw new TypeError( 'Array.prototype.reduce ' + 
              'called on null or undefined' );
          }
          if (typeof callback !== 'function') {
            throw new TypeError( callback +
              ' is not a function');
          }

          // 1. Let O be ? ToObject(this value).
          var o = Object(this);

          // 2. Let len be ? ToLength(? Get(O, "length")).
          var len = o.length >>> 0; 

          // Steps 3, 4, 5, 6, 7      
          var k = 0; 
          var value;

          if (arguments.length >= 2) {
            value = arguments[1];
          } else {
            while (k < len && !(k in o)) {
              k++; 
            }

            // 3. If len is 0 and initialValue is not present,
            //    throw a TypeError exception.
            if (k >= len) {
              throw new TypeError( 'Reduce of empty array ' +
                'with no initial value' );
            }
            value = o[k++];
          }

          // 8. Repeat, while k < len
          while (k < len) {
            // a. Let Pk be ! ToString(k).
            // b. Let kPresent be ? HasProperty(O, Pk).
            // c. If kPresent is true, then
            //    i.  Let kValue be ? Get(O, Pk).
            //    ii. Let accumulator be ? Call(
            //          callbackfn, undefined,
            //          « accumulator, kValue, k, O »).
            if (k in o) {
              value = callback(value, o[k], k, o);
            }

            // d. Increase k by 1.      
            k++;
          }

          // 9. Return accumulator.
          return value;
        }
      });
    }

Question1: If you see step 1,

var o = Object(this);

I have checked both values of o and this, by passing an array to the polyfill method. There is no difference between o and this. They both are arrays(array.isarray returned true on both) with the same array value. Why not use below instead..?

var o = this;

Question2: Step 2

var len = o.length >>> 0;

Above line seems to right shift the o.length(32 bits). However no.of bits shifted is 0. So what advantage do we get by shifting 0 bits... Why not use below instead...?

var len = o.length;

Question 3: The first while condition inside else as below

 while (k < len && !(k in o)) {
    k++;
  }

Initially k is set to 0 and it always seems to exist in o. So this while loop condition never gets to be true. So why do we need this while loop, if it never gets inside.


回答1:


Question 1:

To make sure reduce is called on an object as reduce could be called through Function#call, Function#apply or even bound Function#bind:

Array.prototype.reduce.call(undefined, function() {});

So when accessing properties such as length, an error saying can't access property **** of undefined won't be thrown.

NOTE: the example above uses the native reduce which actually throws an error if not provided with an object.

Question 2:

To always have a valid integer value as length (even if it doesn't exist):

console.log(5 >>> 0);         // 5
console.log(5.5 >>> 0);       // 5
console.log("5" >>> 0);       // 5
console.log("hello" >>> 0);   // 0
console.log(undefined >>> 0); // 0

Question 3:

To deal with sparse arrays:

var arr = [5, 6];
arr[7000000] = 7;

arr.reduce(function(acc, v, i) {
  console.log("index:", i);
}, 0);

It won't go through all the indices from 0 to 7000000, only those that really exist.



来源:https://stackoverflow.com/questions/47839818/array-reduce-polyfill-explanation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!