Polyfill for bind(), Step-by-step

Bharat Sahu
3 min readMar 28, 2021

--

Polyfill for bind() method

Polyfill is nothing but support to older browsers which doesn’t have new methods. In this tutorial, you’ll learn how to write the Polyfill for the `bind()` method in step by step.

first of all, you need to see the `bind()` method, and how it works. look at the snippet below:

let name = {    firstName: "John",    lastName: "Doe"}
function printFullName () { console.log(this.firstName + ' ' + this.lastName)}
let printName = printFullName.bind(name)

If you need to create your own `bind()` method, you’ve to breakdown the above-mentioned snippet.

First, you need to make it available for all the method so we’re going to take help from the `prototype` of `Function`, The snippet will be like:

Function.prototype.polyfill_bind = function () {    //...}

The polyfill_bind() is a user-defined function you can name anything you want and, now it will be available for any function you define in your code like other functions toString(), toLocaleString(), etc.

And now we’re able to make a call similar to the original `bind()` method:

    printFullName.polyfill_bind(name)

Wait it is not completed yet! need to implement logic so it can work exactly like the `bind()` method. As we know the `bind()` method returns a method after creating a new copy of the original method so we make a function call later so we need to return a function whenever we make a call to our `polyfill_bind()`.

Function.prototype.polyfill_bind = function () {    return function () {        // ...    }}let showName = printFullName.polyfill_bind(name);showName();

We have created the basic skeleton for our `polyfill_bind()` but, still we haven’t implemented actual logic on how `bind()` works. So first we need to manage the function call we’re trying to bind with the particular object.

Function.prototype.polyfill_bind = function () {    let context = this;    return function () {        context.call(/* Need to pass arguments */)    }}

As we know, the first argument for the `bind()` method is always an object for which the callee bind to be and it can be any number of argument so we can take it as Rest parameter or `varargs`, then the above can be written as:

Function.prototype.polyfill_bind = function (...args) {    let context = this;    return function () {        context.call(args[0])
}
}

We’re almost there, we also need to take care of other arguments that can be passed with our `polyfill_bind()` and the method which copied using the `polyfill_bind()` method, and it can be any number of arguments so I’m converting it to `apply()` cause it is similar to `call() ` method but it takes an array as in argument:

Function.prototype.polyfill_bind = function (...args) {    let context = this;    let params = args.slice(1)    return function (...args2) {        context.apply(args[0], [...params, ...args2] )    }}

Don’t confuse here, we’re using the Spread operator or the three-dot notation to concat two arrays here. The first array is `param`, we sliced out the first element from it, and the second array is `args2`, which we’re taking as the argument from the method, i.e. `showName(value1, value2, …valueN)`.

Or we can make it with `call()` method version by replacing line `context.apply(args[0], […params, …args2] )` with:

    context.call(args[0], ...params, ...args2)

So the full implementation of our polyfill for `bind()` is which works exactly like the `bind()` method:

let name = {    firstName: "John",    lastName: "Doe"}
function printFullName (city, country) { console.log(this.firstName + ' ' + this.lastName + ' from ' + city + ', ' + country)}Function.prototype.polyfill_bind = function (...args) { let context = this; let params = args.slice(1) return function (...args2) { context.apply(args[0], [...params, ...args2] ) // Or // context.call(args[0], ...params, ...args2) }}let showName = printFullName.polyfill_bind(name, 'Jabari village')showName('Wakanda');// Output: John Doe from Jabari village, Wakanda

References:

  1. Function.prototype.apply()
  2. Function.prototype.bind()
  3. Function.prototype.call()

See more on web from the author:

--

--