How to Polyfill ES6 Arrays Using Lodash

This article provides a direct guide on polyfilling unsupported ECMAScript 6 (ES6) Array methods using the Lodash JavaScript library. Legacy JavaScript runtimes often lack native implementations of essential methods such as Array.from, Array.prototype.find, Array.prototype.findIndex, and Array.prototype.fill. By integrating Lodash's utility functions defensively into native prototypes or using modular import strategies, developers can guarantee cross-environment compatibility without degrading runtime security or performance.

Essential ES6 Array Polyfills via Lodash

Lodash provides modular, battle-tested utilities that directly replicate or exceed the specifications of ES6 Array operations. The following mapping identifies common native methods and their Lodash equivalents:

Safe Prototype Patching Pattern

To polyfill missing array features directly onto Array.prototype without causing prototype pollution or enumerable property issues, use Object.defineProperty. This ensures the polyfilled methods remain non-enumerable, matching native JavaScript behavior.

import find from 'lodash/find';
import findIndex from 'lodash/findIndex';
import fill from 'lodash/fill';

function configureArrayPolyfills() {
  if (!Array.prototype.find) {
    Object.defineProperty(Array.prototype, 'find', {
      value: function (predicate, thisArg) {
        return find(this, typeof predicate === 'function' ? predicate.bind(thisArg) : predicate);
      },
      writable: true,
      configurable: true,
      enumerable: false,
    });
  }

  if (!Array.prototype.findIndex) {
    Object.defineProperty(Array.prototype, 'findIndex', {
      value: function (predicate, thisArg) {
        return findIndex(this, typeof predicate === 'function' ? predicate.bind(thisArg) : predicate);
      },
      writable: true,
      configurable: true,
      enumerable: false,
    });
  }

  if (!Array.prototype.fill) {
    Object.defineProperty(Array.prototype, 'fill', {
      value: function (value, start, end) {
        return fill(this, value, start, end);
      },
      writable: true,
      configurable: true,
      enumerable: false,
    });
  }
}

configureArrayPolyfills();

Static Method Implementation: Array.from

Static methods like Array.from require binding directly to the Array constructor rather than its prototype:

import toArray from 'lodash/toArray';

if (!Array.from) {
  Object.defineProperty(Array, 'from', {
    value: function (arrayLike, mapFn, thisArg) {
      const result = toArray(arrayLike);
      if (typeof mapFn === 'function') {
        return result.map(mapFn, thisArg);
      }
      return result;
    },
    writable: true,
    configurable: true,
    enumerable: false,
  });
}

Build-Time Module Aliasing

Direct prototype mutation can introduce side effects in shared codebases. A cleaner alternative is to alias native calls to Lodash at compile time using build tools like Webpack or Babel.

Babel Plugin Configuration

Using babel-plugin-transform-imports or custom AST rewrites, calls to missing array helpers can be redirected to Lodash modules automatically:

{
  "plugins": [
    [
      "transform-imports",
      {
        "lodash": {
          "transform": "lodash/${member}",
          "preventFullImport": true
        }
      }
    ]
  ]
}

Defensive Considerations

  1. Check for Native Support First: Never overwrite an existing implementation. Native engine optimizations perform significantly faster than user-space polyfills.
  2. Enforce Non-Enumerability: Always use Object.defineProperty instead of direct assignment (Array.prototype.method = ...) to prevent polyfilled methods from leaking into for...in loops.
  3. Modular Consumption: Import modular packages (e.g., lodash/find) rather than the entire library (lodash) to minimize bundle size impact in client-facing applications.