DIY — Function.prototype.bind() in Javascript

NISARG SHAH
4 min readSep 1, 2019

I often find it difficult to memorize the purpose of various built-in functions in Javascript. What usually helps is to understand their inner mechanics, sort of an algorithm of how I would implement a function. Here’s an attempt to do so for Function.prototype.bind() method.

Let’s understand how it works by looking at some examples.

// Let's define a simple sum function.
var sum = (a, b) => a + b;
// Let's BIND the first parameter to value 5.
var sum5 = sum.bind(null, 5);
// So, now sum5 is a new function and you need to pass only one value to it.
sum5(10); // -> Returns 15
sum5(15); // -> Returns 20
// Let's try something else.
var sum10 = sum.bind(null, 10);
sum10(10); // -> Returns 20
sum10(100); // -> Returns 110

You get the point.

Here’s how MDN describes the function:

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.

So by invoking sum.bind(null, 10) we get a function that has its this value bound to null and the first parameter bound to 10.

Let’s look at another example to get a better idea.

var sum = (a, b, c) => a + b + c;var sum_5 = sum.bind(null, 5);
sum_5(10, 20); // -> Returns 35
var sum_5_10 = sum_5.bind(null, 10);
// OR
// var sum_5_10 = sum.bind(null, 5, 10);
sum_5_10(20); // -> Returns 35// You can even bind the third parameter.
var sum_5_10_20 = sum_5_10.bind(null, 20);
sum_5_10_20(); // -> Returns 35

Let’s ignore the first argument of the function for a while. I will focus on trying to replicate the behavior of the remaining part.

Binding for functions having two parameters

Let’s create a separate function customBind and assign to to Function.prototype object so that it may be used in a fashion similar to Function.prototype.bind().

// param1 is the first parameter of the function that takes two arguments.
// I will skip the implementation of `thisArg` for now.
Function.prototype.customBind = function(thisArg, param1) {
// `this` points to the function on which we call customBind method.
// `that` saves a reference to `this` such that it may be accessible in functions below through a closure.
var that = this;

// Need to return a function that takes the second parameter, and returns the sum of first parameter and second parameter.
return function(param2) {
// Invoke the original function passing the first and the second parameter, and return the result.
return that(param1, param2);
}
}

Let’s try it out with our sum function.

var sum5 = sum.customBind(null, 5);
sum5(10); // -> Returns 15

Working with any number of parameters

We can make the customBind function work for three or more parameters with little effort:

Function.prototype.customBind = function(thisArg, param1) {
var that = this;
return function() {
// `arguments` is an array like object that gets all arguments passed to this function call.
// `...arguments` will expand the remaining arguments, and pass into the original function as it is being invoked.
return that(param1, ...arguments);
}
}

It is worth noting the two concepts at play here:

  1. First is arguments: It contains the list of all arguments passed to the function call. This allows us to bind to a function having any number of parameters.
  2. Second is destructuring assignment: It allows us to pass all arguments into the function from 2nd position onward.

Let’s try it out:

var sum = (a, b, c) => a + b + c;var sum5 = sum.customBind(null, 5);
sum5(10, 15); // -> Returns 30
// Going one step further.
var sum5_10 = sum5.customBind(null, 10);
sum5_10(15); // -> Returns 30

Passing multiple parameters to the bind function

There is still a problem. With bind we can get sum5_10 directly from sum function — without having to call bind twice. We cannot do that with the customBind function.

var sum = (a, b, c) => a + b + c;// Binding two arguments using `bind`.
var sum5_10 = sum.bind(null, 5, 10);
sum5_10(15); // -> Returns 30
// Binding two arguments using `customBind`.
sum5_10 = sum.customBind(null, 5, 10);
sum5_10(15); // -> Returns NaN

This little problem can also be fixed by using arugments and destructuring assignment:

Function.prototype.customBind = function(thisArg, ...params) {
var that = this;
return function(...otherParams) { // Pass first N parameters, followed by following K parameters.
return that(...params, ...otherParams);
}
}

Let’s try it out with the sum function that accepts 3 parameters:

var sum = (a, b, c) => a + b + c;
var sum5_10 = sum.customBind(null, 5, 10);
sum5_10(15); // -> Returns 30
sum5_10(5); // -> Returns 20

It also works with a function that accepts 4 parameters:

var sum = (a, b, c, d) => a + b + c + d;
var sum5_10 = sum.customBind(null, 5, 10);
sum5_10(15, 20); // -> Returns 50
sum5_10(5, 10); // -> Returns 30

Just for fun, let’s have a function that will return the sum of any number of arguments, and see if the customBind function works with that.

var sum = function() {
// See the following if you are not familiar with Array.prototype.reduce: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
return Array.from(arguments)
.reduce((a, b) => a + b);
}
sum(5, 10); // -> Returns 15
sum(5, 10, 15); // -> Returns 30
sum(5, 10, 15, 20); // -> Returns 50
var sum5 = sum.customBind(null, 5);
sum5(10); // -> Returns 15
sum5(10, 15); // -> Returns 30
var sum5_10 = sum.customBind(null, 5, 10);
sum5_10(5); // -> Returns 20
sum5_10(5, 10); // -> Returns 30
sum5_10(5, 10, 15); // -> Returns 45

That’s it for now! I will try to cover the implementation of thisArg — the first argument passed into bind function sometime in future.

Hope this helps.

--

--