Polyfills

·

4 min read

Polyfills

a polyfill is a piece of code (usually in JS) that provides modern functionality on older browsers that do not natively supports.

Map()

The map function in javascript is used to transform array by applying a function to each element in the array.

It creates a new array without modifying the original array

const numbers = [1, 2, 3, 4]
const newNumber = numbers.map(i => i * 2); // Output : [2, 4, 6, 8]

Now lets write a polyfill for this map function. Array.prototype.map

if(!Array.prototype.myMap){
    Array.prototype.myMap = function(callback) {
        let result = [];

        for(let i=0; i<this.length; i++) {
            result.push(callback(this[i], i, this))
        }    

        return result;
    }
}

In the above custom map function,

  • callback is what we provide in the map. arr.map((num,i) => num * 2) here (num, i) is the callback passed for the map.

  • In our custom function, we will define a new array (because map returns new array)

  • In the for loop, we will pass the current element, it’s index and the actual array in the callback for each element.

  • and we will return the final modified array.

forEach()

The forEach function is used to loop through an array and executes the function for each elements. Unlike map(), it does not returns the new array, it performs action for each item.

const numbers = [1, 2, 3];
let sum = 0;
numbers.forEach(i => sum += i); // Output sum = 6

let’s write the polyfill for myForEach

if(!Array.prototype.myForEach) {
    Array.prototype.myForEach = function(callback) {
        for(let i=0; i<this.length; i++) {
            callback(this[i], i, this)
        }
    }
}

Here forEach will perform some action on each element. So in the callback, we will pass the current element, index and the actual array

filter()

The filter() function is used to create a new array with the elements that satisfy the certain condition (passed by the user).

const numbers = [1, 2, 3, 4];
const eventNumbers = numbers.filter(i => i%2 === 0); // Output : [2, 4]

let’s write the polyfill for filter

if(!Array.prototype.myFilter) {
    Array.prototype.myFilter = function(callback) {
        let result = [];
        for(let i=0; i<this.length; i++) {
            if(callback(this[i], i, this)) {
                result.push(this[i])
            }
        }
        return result; 
    }
}

Here, inside the loop, check if the callback condition is true, if true then only push the element to the new array.

reduce()

The reduce function used to reduce an array to a single value by applying the callback for each element, from left to right

const numbers = [1, 2, 3, 4]
const sum = numbers.reduce((acc, cur) => acc + cur, 0) // Output : 10

reduce function takes to arguments, on is callback which runs for each element, and second is initialValue.

in the callback we are having

ParamsDescriptinon
accumulatorthe initialValue or the result from the previous step
currentValuecurrent element that is being processed
currentIndex (optional)index of the current element
array (optional)original array

Let’s write the polyfill for reduce

if(!Array.prototype.myReduce) {
    Array.prototype.myReduce = function(callback, initialValue) {
        var accumulator = initialValue;
        for(i=0; i<this.length; i++) {
            accumulator = accumulator ? cb(accumulator, this[i], i, this) : this[i]
        }

        return accumulator;
    }
}

call()

The .call() method used to call a function with a specific this value and pass arguments one by one.

Basic syntax :

functionName.call(thisArgs, arg1, arg2, ...)

thisArgs → The value you want this to refer to

arg1, arg2, .. → Arguments you want to pass to the function (optional)

Example:

const user = {
    name: "AkLuffy",
    age: "24"
}

function greetUser(city) {
    console.log(`This is ${this.name} of age ${this.age}. He is from ${city}`)
}

greetUser.call(user, "Bengaluru") // Output : This is AkLuffy of age 24. He is from Bengaluru

Let’s write polyfill for call

if(!Function.prototype.myCall) {
    Function.prototype.myCall = function(context = {}, ...args) {
        if(typeof this !== 'function') {
            throw new Error ("It's not a proper function")
        }

        context.fn = this;
        context.fn(...args);
    }
}

Here first we will check is this property is function or not. If so then we will assign the context’s function and for that function we will pass the arguments.

apply()

This is similar to .call() method, but here we pass the arguments as the array.

Syntax :

functionName.apply(thisArgs, [arg1, arg2])

Let’s write polyfill for apply

if(!Function.prototype.myApply) {
    Function.prototype.myApply= function(context = {}, args = []) {
        if(typeof this !== 'function') {
            throw new Error ("It's not a proper function")
        }

        if(!Array.isArray(args)) {
            throw new Error ("CreateListFromArrayLike called on non-object")
        }

        context.fn = this;
        context.fn(...args);
    }
}

bind()

The bind() method is used to create a function to call later with specific this. It returns the new function with this bound to the provided context.

Syntax:

function.bind(thisArgs, arg1, arg2, …)

Let’s write polyfill for bind()

if(!Function.prototype.myBind) {
    Function.prototype.myBind = function(context = {}, ...args) {
        if(typeof this !== 'function') {
            throw new Error ("the provided context is not a function")
        }

        context.fn = this;
        return function(...newArgs) {
            return context.fn(...args, ...newArgs)
        }

    }
}