Javascript bind() – explained in depth

Implement myBind() on Function prototype imitating bind()’s functionality. Of course you can’t call bind() within your implementation.

NOTE: It is not a good idea to override/modify prototype in javascript, this exercise is just to understand how things work in javascript.

Before we start implementing myBind() let’s understand a little bit about bind().

Javascript bind():

  • bind() is a method defined on Function prototype which is accessible to each and every function object.
// create a sample function

var sample = function() {
    console.log("Inside sample function");
};

console.log('bind' in sample);                 // prints true
console.log(sample.bind instance of Function); // prints true
  • bind() always returns a function (same function on which bind is called)
// ... continued

let val = sample.bind();
console.log(val instance of Function); // prints true
val();  // prints "Inside sample function"
  • bind() takes new context as its first argument with which the returned function (when called) gets executed.
let add = function() {
    return this.num1 + this.num2;
};

let obj1 = { num1: 10, num2: 20 };
let obj1AddFn = add.bind(obj1);

// Now "this" inside obj1AddFn points to obj1
console.log(obj1AddFn());       // prints 30

let obj2 = { num1: 20, num2: 40 };
let obj2AddFn = add.bind(obj2);

// Now "this" inside obj2AddFn points to obj2
console.log(obj2AddFn());       // prints 60
  • bind() also takes additional arguments which gets passed each time the returned function gets executed
let context = { num1: 10, num2: 20 };
let sample = function() {
    console.log(this);
    console.log(arguments);
}

let boundSample = sample.bind(context, 100, 200);
boundSample();         // prints this as { num1: 10, num2: 20 }
                       // arguments are [100, 200]

boundSample(300);      // prints this as { num1: 10, num2: 20 }
                       // arguments are [100, 200, 300]

boundSample(300, 400); // prints this as { num1: 10, num2: 20 }
                       // arguments are [100, 200, 300, 400]

Implementation:

Since we now thoroughly understand how bind works let try to implement myBind on Function prototype:

Function.prototype.myBind = function (context, ...fixedArgs) {
    let that = this; // this here is the method which needs to be
                     // invoked by the returned function

    return function (...dynamicArgs) {
        let args = fixedArgs.concat(dynamicArgs);
        return that.apply(context, args);
    }
}

NOTE: The implementation can be optimized further by using arrow functions, I have kept it this way to make it more readable.

Above is a basic implementation of myBind():

  • which is accessible to every function since it is defined on Function prototype
  • which returns a function that when invoked gets executed with the context it was bound to
  • The returned function of myBind() receives both the fixed args that were bound and also dynamic args that are passed during its invocation.

Here is a small example which tests our new myBind function:

let context = { num1: 10, num2: 20 };
let sample = function() {
    console.log(this);
    console.log(arguments);
}

let k = sample.myBind(context, 100, 200);
k();          // prints this as { num1: 10, num2: 20 }
              // arguments are [100, 200]

k(300);       // prints this as { num1: 10, num2: 20 }
              // arguments are [100, 200, 300]

k(300, 400);  // prints this as { num1: 10, num2: 20 }
              // arguments are [100, 200, 300, 400]

Check this page for more such questions

Advanced Javascript interview questions

Introduction

I usually find it difficult to find advanced Javascript coding interview questions so I would like use this space to list some of the challenging Javascript coding questions that I have come across.

Questions

  1. Implement a function on Function prototype called myBind() which imitates the functionality of bind()
  2. Implement debounce
  3. Implement getElementsByClassName()
  4. Implement a method to flatten a nested Array for eg: [[1,2,[3]], 4,[5,6]] => [1,2,3,4,5,6]
  5. more coming soon …