# 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

```javascript
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`

```javascript
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.

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

let’s write the polyfill for `myForEach`

```javascript
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).

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

let’s write the polyfill for filter

```javascript
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

```javascript
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

| Params | Descriptinon |
| --- | --- |
| accumulator | the initialValue or the result from the previous step |
| currentValue | current element that is being processed |
| currentIndex (optional) | index of the current element |
| array (optional) | original array |

Let’s write the polyfill for reduce

```javascript
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:

```javascript
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

```javascript
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`

```javascript
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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1739441229328/5b069233-47ae-45f7-823b-b395c01bb1f5.png align="center")

**Syntax:**

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

Let’s write polyfill for bind()

```javascript
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)
        }

    }
}
```
