Explorer
JavaScript

polyfills for array methods

JavaScript Theory & Concepts

Polyfills for Array Methods

Mastering prototype inheritance and edge-case handling by implementing map, filter, and reduce from scratch.

📖 The Story & Real-World Analogy

The Universal Electrical Adapter

"When you travel to a historic hotel in an old city with a modern gadget, the wall outlet might lack the modern 3-pin USB-C port. You pull a universal travel adapter out of your suitcase. It plugs into the old outlet and provides the exact same voltage and socket interface. A polyfill is that adapter for JavaScript runtimes: if an older browser lacks `Array.prototype.map`, our polyfill attaches a handcrafted version to the prototype so modern code runs without errors."

Writing array polyfills is one of the most common senior frontend interview tests. It tests your mastery of `Array.prototype`, the dynamic `this` keyword, callback arguments, and edge-case defensiveness.

⚙️ How It Works Under The Hood (Step-by-Step)
1

Feature Detection Guard

Always check `if (!Array.prototype.customMethod)` before defining. Never overwrite native implementations which are heavily optimized at the C++ level.

2

Binding to the Caller with `this`

Inside `Array.prototype.myMethod = function(...)`, `this` references the array instance executing the call. We must validate that `this != null`.

3

Validating Callback Functions

If the caller passes a non-function as the callback, throw `new TypeError(callback + " is not a function")` to match ECMAScript spec.

4

Handling Holes in Sparse Arrays

Native methods skip missing indices. Using `i in this` or `Object.hasOwn(this, i)` ensures unassigned indexes are not passed to the callback.

5

Handling reduce() initialValue Semantics

If `initialValue` is provided, accumulator starts with it and index starts at 0. If omitted, accumulator takes `this[0]` and index starts at 1.

💻 Interactive Code Walkthrough

Production-grade polyfills for myMap and myReduce:

JAVASCRIPT
// Polyfill for Array.prototype.map
Array.prototype.myMap = function(callback, thisArg) {
  if (this == null) throw new TypeError("Cannot iterate over null or undefined");
  if (typeof callback !== "function") throw new TypeError(callback + " is not a function");

  const O = Object(this);
  const len = O.length >>> 0; // Unsigned 32-bit int conversion
  const result = new Array(len);

  for (let i = 0; i < len; i++) {
    if (i in O) {
      result[i] = callback.call(thisArg, O[i], i, O);
    }
  }
  return result;
};

// Polyfill for Array.prototype.reduce
Array.prototype.myReduce = function(callback, initialValue) {
  if (this == null) throw new TypeError("Cannot reduce null or undefined");
  if (typeof callback !== "function") throw new TypeError(callback + " is not a function");

  const O = Object(this);
  const len = O.length >>> 0;
  let k = 0;
  let accumulator;

  if (arguments.length >= 2) {
    accumulator = initialValue;
  } else {
    // Find first present index if initialValue is omitted
    let kPresent = false;
    while (k < len && !kPresent) {
      if (k in O) {
        accumulator = O[k];
        kPresent = true;
      }
      k++;
    }
    if (!kPresent) throw new TypeError("Reduce of empty array with no initial value");
  }

  for (; k < len; k++) {
    if (k in O) {
      accumulator = callback(accumulator, O[k], k, O);
    }
  }
  return accumulator;
};

// Test
const nums = [1, 2, 3];
console.log(nums.myMap(x => x * 2));
console.log(nums.myReduce((acc, x) => acc + x, 0));
Console Output:
CODE
[ 2, 4, 6 ]
6
⚠️ Common Pitfalls & Interview Traps
Trap
Calling reduce on Empty Array with No Initial Value

The Risk: `[].reduce((a, b) => a + b)` throws `TypeError: Reduce of empty array with no initial value` in ECMAScript spec.

The Fix: Ensure your polyfill checks for `arguments.length >= 2`, and if empty with no initial value, throws a TypeError.

Trap
Using Arrow Functions for Polyfill Implementations

The Risk: Declaring `Array.prototype.myMap = (callback) => { ... }` binds `this` lexically to the enclosing scope (window/global), breaking access to the array instance.

The Fix: Always use traditional `function(...)` declarations so `this` dynamically refers to the calling array.

⚡ 30-Second Quick Revision Cheat Sheet (TL;DR)
  • ✓ Polyfills bridge language gaps across browser versions.
  • ✓ Never use arrow functions on prototypes (`this` will point to window/global).
  • ✓ `this` inside the method is the array instance.
  • ✓ In `reduce()`, check `arguments.length >= 2` to distinguish explicit `undefined` from omitted initial value.
  • ✓ Skip empty slots in sparse arrays using `if (i in this)`.

Finished this lesson?

Mark this chapter complete to update your learning streak and unlock the next lesson.