DEV Community

asiddharth94
asiddharth94

Posted on

bind() polyfill - JavaScript

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

Let me try to simplify it for you! πŸ˜ƒ

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() {}
Enter fullscreen mode Exit fullscreen mode

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() {}
}
Enter fullscreen mode Exit fullscreen mode

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() {}
}
Enter fullscreen mode Exit fullscreen mode

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();
    }
}
Enter fullscreen mode Exit fullscreen mode

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 and spread syntax) and set the context in our myBind().

πŸ’‘ Function.prototype.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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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 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() πŸš€

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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 and spread 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]);
    }
}
Enter fullscreen mode Exit fullscreen mode

ANNNDDDDD, THAT IS IT ! YAY !

Top comments (0)