JavaScript Call() & Apply() VS Bind()

Javascript call() & apply() vs bind()?

I created this comparison between function objects, function calls, call/apply and bind a while ago:

Sample Image

.bind allows you to set the this value now while allowing you to execute the function in the future, because it returns a new function object.

what's the difference between 'call/apply' and 'bind'

bind returns a function which will act like the original function but with this predefined. It is usually used when you want to pass a function to an event handler or other async callback.

call and apply will call a function immediately letting you specify both the value of this and any arguments the function will receive.

Your second example defines an anonymous function which calls apply. This is a common pattern; bind provides a standard implementation of that which allows you to do it with a simple function call (thus being quicker and easier to write).

Call/Bind/Apply vs prototype

The reason you don't want to use Object.prototype.sayHi = function(){} is that once you do, everything that has Object in its prototype chain will be able to use sayHi. That's the core of prototypical inheritance.

It's OK to add things to the prototype of objects that you create (and it's just considered bad practice to add to Object.prototype). Just understand that when you do, anything in your objects prototype chain will be able to use that function.

function sayHello() {
console.log("hello");
}

// Bad
Object.prototype.hello = sayHello;
Date.hello(); // Prints hello

Call, Apply, and Bind are actually slightly different from adding to prototype and Bind is also different from Call and Apply as well.

Call and Apply

Function.call() and Function.apply() use whatever function you are calling or applying at the moment of the call or apply.

For example, if we wanted to use the forEach() method on a NodeList

var els = document.querySelectorAll("div");
Array.prototype.forEach.call(els, function(el){
el.classList.add("someClass");

The big difference between call and apply is that call takes a variadic argument and apply takes an Array.

function say() {
console.log(arguments);
}
say.call(this, "a", "b");
say.apply(this, ["a", "b"]);

Bind

Using Function.bind() is actually a different thing though. Bind lets you create a context binding where you can call a function from a specific context when you want.

function honk() {
console.log(this.sound);
}

function Car() {
this.sound = "honk";
}

function Van(){
this.sound = "beep";
}
var c = new Car();
var v = new Van();

var ftorCar = honk.bind(c);
var ftorVan = honk.bind(v);

ftorCar(); // prints honk
ftorVan(); // prints beep

You can now pass ftorCar around and call it when you want to and it will have the correct scope "binding".

Comparison of call, apply, bind in a simple example

All three of your result vars are referencing functions hence these vars are functions themselves. When you use the bind method, you are assigning the printName function to be executed AFTER the fact whereas call and apply methods are run immediately. In order to get "Richard" returned from result3 you simply need to invoke it as a function like this: result3(); Attempting to run result1() or result2() the same way will show an error because those methods were applied on the fly and are not available as functions after the fact.

When this line is read:

var result1 = printName.call(obj1);

...then the printName function is run immediately and the value returned from that function is assigned to result1. Same for result2.

When this line is read:

var result3 = printName.bind(obj3);

...then the function itself is assigned to result3 and can be run by typing

result3();

So call and apply are used for getting a value returned whereas bind is used for getting a function returned.

With regard to call and apply, since you do not have any references inside any of your objects or prototype methods to the THIS keyword, you don't need to pass in a redefined THIS context. Call and Apply methods are generally best when you need to change context of a method belonging to another object. Look at this extended example of adding a new method to obj1:

obj1.sayHello = function() {
console.log('Hello ' + this.name);
}

obj1.sayHello() //returns "Hello Peter"

If you want to use the sayHello method inside of obj1 to show data from obj2 then that is where you can use call or apply like this:

obj1.sayHello.call(obj2);  //returns "Hello John"

The big difference between call and apply is when you want to pass parameters into a function that exists in another object. So if we change the sayHello method on obj1 as follows:

obj1.sayHello = function(greeting) {
console.log(greeting + ' ' + this.name);
};

The sayHello function now accepts a parameter. Once again if you call the function like this:

obj1.sayHello('Welcome'); //returns Welcome Peter

but if you want to use this method on obj2 then you would do it like this:

obj1.sayHello.call(obj2, 'Greetings'); //returns Greetings John

When you use the call method, you can pass in parameters using comma separated strings. You can also use apply in this same way except that you would need to pass in an array of values as parameters like this:

obj1.sayHello.apply(obj2, ['Happy Hump Day']); //returns Happy Hump Day John

I hope this helps to clear it up for you.

Cheers,
Jim

Difference between bind, apply and call method?

apply and call are the same thing except one accepts the arguments to be passed to the function in array form the other in parameter form.

bind does the same thing as call or apply depending on the framework you are using but doesn't call the function right away instead it returns a new function with your parameters bound to this and when the function is called from a new scope or context, this will still remain whatever you bound to it. Binding also allows you to prevent your constructors from being "hacked" by apply or call since it will always use the binded parameters for this no matter what someone sends to attempt to override this via call or apply.

Here is an example:

function Profile(u) {
this.user = u;
this.getUser = function () {
return this.user;
};
}

function Profile2(u) {
this.user = u;
this.getUser = (function () {
return this.user;
});
}

function Profile3(u) {
this.user = u;
this.getUser = (function () {
return this.user;
});
}

var x = new Profile('guest');
var x2 = new Profile2('guest');
var x3 = new Profile3('guest');

alert(x.getUser.apply({
user: 'Vinoth'
})); // Vinoth
alert(x2.getUser.call({
user: 'Babu'
})); // babu
alert(x3.getUser.bind(x3).call({
user: 'Nandan'
})); // Guest

What is the difference between call and apply?

The difference is that apply lets you invoke the function with arguments as an array; call requires the parameters be listed explicitly. A useful mnemonic is "A for array and C for comma."

See MDN's documentation on apply and call.

Pseudo syntax:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, ...)

There is also, as of ES6, the possibility to spread the array for use with the call function, you can see the compatibilities here.

Sample code:

function theFunction(name, profession) {
console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator


Related Topics



Leave a reply



Submit