bind() polyfill - JavaScript
Tags: javascript, functions, bind, polyfill
Published: 2022-03-06 14:59:56

"**Write your own 'bind' function**" - pretty common in interviews, right?

Let me try to simplify it for you! :smiley:

Let's begin with the *definitions* -

1. **The bind() method creates a new function that, when called, has its _'this'_ keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.**
Refer - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

2. **A polyfill is a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.**
Refer - https://developer.mozilla.org/en-US/docs/Glossary/Polyfill

Now, the fun and easy part. *Implementation* -

First things first, adding our 'myBind' to the prototype (_to be able to use it on other functions, right?_)

```
Function.prototype.myBind = function() {}
```

Now, one thing we know for sure is that the 'bind()' returns a function (copy of the function on which it was called). Let's do that with our own bind(), i.e, myBind()! *One step at a time.*

```
Function.prototype.myBind = function() {
    return function() {}
}
```

Next, as we know the '.bind()' returns a copy of the function on which it was called, let's get the caller function first with the **_this_** inside our '.myBind' function.

```
Function.prototype.myBind = function() {
    //'this' here will be the function on which 'myBind' was called
    var callerFunc = this;
    return function() {}
}
```

Now, we'll call the callerFunc in our returned function, because that is our ultimate goal, right?

I'm using the 'call' method because we need to set the **_this_** context in the callerFunc based on the arguments.

```
Function.prototype.myBind = function() {
    //'this' here will be the function on which 'myBind' was called
    var callerFunc = this;
    return function() {
        callerFunc.call();
    }
}
```

Next, the bind() method accepts a list of parameters. First one is the object to which the **_this_** refers in the returned copy function, followed by the function parameters.

So, let's get the arguments (using [rest](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) and [spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) syntax) and set the context in our myBind().

💡 [Function.prototype.call()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) 's first arg is the **_this_** arg, followed by list of args.

```
Function.prototype.myBind = function(...args) {
    //'this' here will be the function on which 'myBind' was called
    var callerFunc = this;
    var thisArg = args[0];
    return function() {
        callerFunc.call(thisArg);
    }
}
```

Now we have the **_this_** context set properly, let's handle the next list of parameters, which **myBind()** might receive (optional params).

**HOLD ON!!**
We can get the remaining parameters (i.e, other than thisArg) passed to myBind() by using the [slice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) method on our 'args' array.

`var params = args.slice(1)`

**BUT, the 'params' is an array now and we can only pass comma separated values to our call() method.** _What to do?_

Here comes,[ Function.protoype.apply()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) 🚀

The apply() method is similar to call(). Only difference is that it accepts argsArray[] as the second argument. Problem Solved!!! Let's do the changes.

```
Function.prototype.myBind = function(...args) {
    //'this' here will be the function on which 'myBind' was called
    var callerFunc = this;
    var thisArg = args[0];
    var params = args.slice(1);
    return function() {
        // using apply instead of call!
        callerFunc.apply(thisArg, params);
    }
}
```

Last step, we also need to take care of the arguments which might not be passed in the beginning to myBind() but instead, received when the returned function from myBind() is called.

Let's use the [rest](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) and [spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) and achieve our goal!

```
Function.prototype.myBind = function(...args) {
    //'this' here will be the function on which 'myBind' was called
    var callerFunc = this;
    var thisArg = args[0];
    var params = args.slice(1);
    return function(...remArgs) {
        // using apply instead of call!
        callerFunc.apply(thisArg, [...params, ...remArgs]);
    }
}
```

ANNNDDDDD, THAT IS IT ! YAY !