Javascript call() & apply() vs bind()?
I created this comparison between function objects, function calls, call/apply
and bind
a while ago:
.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
Controller Not a Function, Got Undefined, While Defining Controllers Globally
How to Tell If Browser/Tab Is Active
How to Get the Youtube Video Id from a Url
How to Handle Newlines in Json
Serving Gzipped CSS and JavaScript from Amazon Cloudfront via S3
How to Preserve Aspect Ratio When Scaling Image Using One (Css) Dimension in IE6
React Native Use Variable for Image File
How to Perform SQL "Like" Operation on Firebase
Difference Between Domcontentloaded and Load Events
Why This JavaScript Regex Doesn't Work
How to Simulate a Click With JavaScript
Fastest Method to Replace All Instances of a Character in a String