Polyfill for Array Method: Map - Learn the right way

A polyfill is a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it. MDN

In most of the product-based companies' interviews, the most common question asked is to write the polyfill of any array methods. To understand the candidate's depth of knowledge in javascript this is a good question to start but often we miss out on many edge cases while implementing polyfill

All the blogs or videos explaining Map polyfill often miss some cases like

  • Calling the map callback function with the correct thisArg and this.

  • Passing the index and array to the map callback.

  • Sparse arrays (e.g. [1, 2, , 4]). The empty values should be ignored while traversing the array.

The above edge cases are missing while writing Map polyfills

As the map array method has all this built-in functionality we are missing the above cases.

This may lead to rejection in interviews

As half knowledge is always more dangerous than none ⛔️

Today we deep dive into the map array method and write a polyfill of myMap

Which satisfies all cases of the map array method

Array.prototype.myMap = function (callbackFn, thisArg) {
  const len = this.length;
  const array = new Array(len);

  for(let k=0; k<len; k++) {
    if(Object.hasOwn(this,k)) {
      array[k] = callbackFn.call(thisArg, this[k], k, this)
    }
  }
  return array;
};

Object.hasOwn(this,k)

The above step will take care of sparse arrays edge case

const identityMethod = (element) => element;
const square = (element) => element * element;

test('test for sparse arrays', () => {    
expect([9, 8, , 6].myMap(identityMethod)).toEqual([9, 8, , 6]);     
expect([1, 2, , 4].myMap(square)).toEqual([1, 4, , 16]);  
});

We can pass arguments, element, index and array in the map array method. so we are also returning thisArg, this[k], k, this

const multiplyWithIndex = (element, index) => element * index;
const squareAlternative = (element, index, array) => element * array[index];

test('test for multiple with index and square alternative', () => {
    expect([1, 2, 3].myMap(multiplyWithIndex)).toEqual([0, 2, 6]);
    expect([1, 2, 3, 4].myMap(squareAlt)).toEqual([1, 4, 9, 16]);
  });

Final edge case, we can send arguments in the map array method

const usesThis = function (element) {
  return element * this;
};
const usesThisArrowFn = (element) => element * this;

test('uses this argument', () => {    
expect([1, 2, 3, 4].myMap(usesThis)).toEqual([NaN, NaN, NaN, NaN]);    
expect([1, 2, 3, 4].myMap(usesThis, 10)).toEqual([10, 20, 30, 40]);    
expect([1, 2, 3, 4].myMap(usesThisArrowFn)).toEqual([NaN, NaN, NaN, NaN]);    
expect([1, 2, 3, 4].myMap(usesThisArrowFn, 10)).toEqual([NaN,NaN,NaN,NaN,]);
});

So next time, in an interview if the interviewer asks about writing map polyfill don't miss the above edge cases

Thanks for reading.