Polyfills in JavaScript: What, Why & How?

Prajwal MhaskarPrajwal Mhaskar
4 min read

Understanding Polyfills

When developing modern JavaScript applications, ensuring compatibility across different browsers and environments is a common challenge. New features are frequently introduced in the language, but not all browsers or environments adopt them at the same pace. This is where polyfills come into play.

What is a Polyfill?

A polyfill is a piece of code (usually JavaScript) that provides functionality for a feature that might not be natively supported by all browsers.

Example: If you use fetch method in Internet Explorer browser, you will get an error as the method is not implied in IE. Therefore, it is considered as an old browser.

Polyfills are useful when you want to use a modern feature in your code, but you need to support older browsers (e.g., Internet Explorer, older versions of Firefox, etc.) that don’t have support for that feature.

Common Use Cases

Polyfills are commonly used for the following scenarios:

  1. New JavaScript Methods: Modern methods like Array.prototype.includes(), String.prototype.padStart(), etc.

  2. Web API Support: Features like fetch(), Promise, localStorage, etc.

  3. CSS/HTML Features: New HTML5 elements, CSS Grid, etc.

  4. ES6/ES2015+ Features: Features like let, const, arrow functions, classes, template literals, etc.

How Polyfills work?

Polyfills are like browser fallback code, it checks if the desired feature exist in the current environment, if it doesn’t exist then polyfill implements that feature.

What if your browser doesn’t provide the map( ) function then you will need to code your own map( ) function. To better understand this, we will discuss polyfills for the following methods:

  • Using map( )

  • Using filter( )

  • Using reduce( )

How to write your own Polyfills?

Let’s consider an environment in which the above functions don’t exist. We will code our own map( ), filter( ) and reduce( ) function. These are all higher-order function which is defined inside Array.prototype so that they are accessible to all the array declared.

For creating our own polyfill we need to declare them inside the Array.prototype. It is an important step.

1. Polyfill for map( ) function

Example: We have been given the array and we need to multiply each element by two.

let arr = [1, 2, 3, 4, 5]

if (!Array.prototype.mymap) {
    Array.prototype.mymap = function (userFn) { //userFn is any callback function
        let result = [] //an empty array to store calculated values

        for (let i=0; i<this.length; i++) {
            if (userFn(this[i])) { //this represents current context {1,2,3,4,5}
                result.push(this[i])
            }
        return result
        }
    }
}

console.log(arr.mymap((a) => a*2))

Output:

2
4
6
8
10

2. Polyfill for filter( ) function

Example: Creating our own function like filter( ) function in JavaScript to return values greater than 12.

let arr = [2, 31, 5, 11, 19, 20, 35]

if (!Array.prototype.myfilter) {
    Array.prototype.myfilter = function (userFn) { //userFn is any callback function
        const result = [] //an empty array to store calculated values

        for (let i=0; i<this.length; i++) {
            if (userFn(this[i])) { //this represents current context {2,31,5,11,19,20,35}
                result.push(this[i])
            }
        return result
        }
    }
}

console.log(arr.myfilter((a) => a%2 == 0))

Output:

31
19
20
35

3. Polyfill for reduce( ) function

Example: Find the sum of all the even numbers inside the given array.

let arr = [1, 2, 3, 4]

if (!Array.prototype.myreduce) {
    Array.prototype.myreduce = function (userFn, initial_value) { //userFn is any callback function
        let acc;
        let startIndex = 0; //sets start index to 0

        if (initial_value !== undefined){ //if current array is non-empty
            acc = initial_value; //assign initial value of arr to acc
        }
        else {
            if (this.length === 0) { //throws an error is arr is empty
                throw new TypeError("Reduce of empty array with no initial value")
            }
        acc = this[0]
        startIndex = 1
        }
        for (let i=startIndex; i<this.length; i++) {
            acc = userFn(acc, this[i], i, this) // Here, userFn will get replaced by the called function
        }
        return acc
    }
}

const sum = arr.myreduce((acc, curr, i, arr) => { return acc + curr }, 0)

console.log(sum)

Output:

10

While you can write polyfills yourself, it’s usually easier to use polyfill libraries that are maintained by the community and handle cross-browser compatibility.

  1. Babel Polyfill:

    • Babel is a JavaScript compiler that can transpile modern JavaScript (ES6 and beyond) into older JavaScript versions. It includes a built-in polyfill for many newer features.
  2. core-js:

    • A modular and customizable polyfill library that provides support for modern JavaScript features like Promise, Set, WeakMap, Symbol, and more.
  3. Polyfill.io:

    • A service that provides automatic polyfilling based on the user's browser. You simply include a script, and it delivers the necessary polyfills for the features not supported by that browser.

P.S: You can always improvise your polyfills by throwing/catching errors for different test cases.

15
Subscribe to my newsletter

Read articles from Prajwal Mhaskar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Prajwal Mhaskar
Prajwal Mhaskar