call,apply and bind in javascript

call,apply and bind in javascript

Call vs apply vs bind:-

  • Today we are going to learn about Function prototype methods call , apply and bind. but first, why do we need call, apply and bind?

  • In javascript this does not work the same as java or c++. so with the help of these three methods, you can explicitly provide this to the function to prevent unexpected behavior.

  • You can also use call, apply and bind to write a common function to the objects.

  • this blog is part of a mini-series this in javascript so please do check it out.

call ():

  • syntex of function with call looks like this : functionName.call(obj,functionArgs)

const obj ={num : 3};
const obj2 = {num:5};

function addToThis(a){
  return this.num + a;
}



console.log(addToThis.call(obj,4)); // 7
console.log(addToThis.call(obj2,6)); // 11
  • The first parameter in call() method sets the this value, which is the object, on which the function is invoked upon. In this case, it's the obj object above.

  • After the First argument rest of the arguments are arguments for the original function.

  • we can say that addToThis function was called on obj and obj2.

  • every javascript object has prototype and it has useful methods you can use call to access those methods. for example if you want to access prototype methods of array on argument you can use call.


function callApplication() {
  console.log([].slice.call(arguments, 1, 4));
}
callApplication(1, 2, 3, 4, 5, 6);   //  [2,3,4]

apply :-

  • It is similar to call but second argument is array of arguments.

const obj ={num : 3};
const obj2 = {num:5};

function multiplicationToThis(a, b, c) {
  return this.num * a * b  * c;
}

const args = [1, 3, 5];

console.log(multiplicationToThis.apply(obj, args)); // 45
console.log(multiplicationToThis.apply(obj2, args)); // 75
  • Here we are passing array of arguments instead of passing arguments with comma.
  • We can say that addToThisWithAppy was applied with array of args.

other application :-

  • when you have array and given function does not accept array as argument we can use apply to spread out those array.

const x = [1,2,4,5,7];

console.log(Math.min.apply(this,x)); // output: 1
  • instead of using apply you can also use es6 ... spread operator.

bind :-

  • bind method bounds object with function and return new function and you can that function call later anywhere you want where this will be referencing to the object which you pass with bind method.

const obj = { num: 3 };

const obj2 = { num: 5 };

function multiplyThis(a) {
  return this.num + a;
}

const boundedFunction = multiplyThis.bind(obj);

console.log(boundedFunction(4));  //12
  • Here addToThis is bounded by obj.

appilcation :-

  1. In case of callback function to preserve this we can use bind .

let myObj = {
  asyncGet: function(cb){
    cb();
  },
   parse: function(){
    console.log('parse called');
  },
  render:function(){
    this.asyncGet(function(){
      this.parse();
    }.bind(this))
  }
}

myObj.render();
  • Here normally this in callbackFunction would belong to the window object but using bind we bound this to the myObj. alternative use arrow functions. because it does not have this. so it will take it's parents this.

  • In Functional programming there is concept call partial in which function takes few arguments at front and returns the function; that function will take rest of the arguments and executes the function. we can usebind to achieve this.


function ajax(url,reqObj){
     return ajax.get(url,reqObj);
}

let getBlogs = ajax.bind(this,"/user/blogs");

let blogs = getBlogs({userId:123});
  • Here, ajax.bind takes this and first argument of ajax function and returns the function and that function (getBlogs()) will take remaining arguments and executes the function.this will be very helpful if you want a specific function from abstract function.

  • If you pass null or undefined as a this binding parameter to call, apply, or bind, those values are effectively ignored, and instead the default binding rule applies to the invocation.

function foo() {
    console.log( this.a );
}

var a = 2;

foo.call( null ); // 2
  • call,apply and bind does not effect the arrow function because it does not have this.