Search code examples
javascriptarraysdictionarypolyfills

Confused about polyfill of Array.prototype.reduce


This code is polyfill of Array.prototype.reduce given on Mozilla Developer Network. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.io/#x15.4.4.19
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')
    }

    var O = Object(this)
    var len = O.length >>> 0

    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' is not a function')
    }

    if (arguments.length > 1) {
      T = arguments[1]
    }

    A = new Array(len)
    k = 0

    while (k < len) {
      var kValue, mappedValue

      if (k in O) {
        kValue = O[k]
        mappedValue = callback.call(T, kValue, k, O)
        A[k] = mappedValue
      }
      k++
    }

    return A
  }
}

What I don't understand is these two lines

1.Why not just use this?

var O = Object(this)

2.Is it possible this be null, why need this code below?

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

3.Why we need k in O? while k < len, k always in O, is it useless condition?

if (k in O) {
    kValue = O[k]
    mappedValue = callback.call(T, kValue, k, O)
    A[k] = mappedValue
  }

Solution

  • 1.Why not just use this?

    var O = Object(this)
    

    In Edition 3, an undefined or null thisArg is replaced with the global object and ToObject is applied to all other values and that result is passed as the this value.

    So my guess is that the reasons this is being done is to keep consistency.

    2.Is it possible this be null, why need this code below?

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

    Yes, it is possible for this to be null.

    Execute the following code with and without strict mode. You will notice that in strict mode the output is null, while in the other case its the window.

    // "use strict";
    var x = function(){
        console.log(this);
        return this;
    }
    
    x.call(null);
    

    3.Why we need k in O? while k < len, k always in O, is it useless condition?

    if (k in O) {
        kValue = O[k]
        mappedValue = callback.call(T, kValue, k, O)
        A[k] = mappedValue
      }
    

    Not a useless condition, because it checks if a property exists.(see in operator examples)

    Adding an example with sparse arrays:

    var a = new Array(3);
    console.log(a); // [ , , ]
    console.log(a.length); // 3
    console.log(a[0]); // undefined