If you have been around the js ecosystem for a while there's a good chance you will have seen at least one of apply
,
bind
or call
. Perhaps this was before the days of array functions e.g. () => {}
, and you were tasked with
attaching a handler function to an onClick
event in a react component, something like the following.
<Button onClick={this.eventHandler.bind(this)} />
That being said, in my experience it's not something you need to use every day and if you don't at least know the basics of how to use each one, you might find yourself taken off-guard when thrown a question about one or more of these in a technical interview.
I know this article plays on the fact that we can make ABC from the first letter of each method, but we are going to
start with B
.
Bind
As expressed in the example above, we use the bind
method to explicitly set the context in the target object. It allows
us to ensure we don't lose a reference to this
when the function is called. In order to circumvent even having to use
the bind
keyword, it's possible to achieve the same thing using an arrow function.
<Button onClick={() => this.eventHandler()} />
In fact, when using an arrow function as part of a functional component, you don't even need to worry about using the
bind
keyword at all.
const eventHandler = () => {
// Do something here
};
<Button onClick={eventHandler} />
Although the previous examples have been focused on a common use case in class based components; this is not the only
use of the bind
keyword. At the most basic level we can use it as an instrument for sharing or extending functionality
between objects.
In the following example, the myObj
object requires the use of a logging function but doesn't have
this ability out of the box.
Using the bind
method here allows us to call the log method with the context of myObj
and return My object
instead
of My logger
.
const myObj = {
name: 'My object'
};
const myLogger = {
name: 'My logger',
log: function () {
console.log(this.name);
}
};
const log = myLogger.log.bind(myObj);
log();
One final point to note about the bind
method is that it's possible to pass arbitrary additional parameters which will
get applied upon invocation. This will become more apparent when we look at the next section.
myObj.bind(this, param1, param2, param3);
Call
The call
method is actually very similar to the bind
method. The only real difference is that it is immediately
invoked.
If we go back to our example from the bind
section, you can see that replacing bind
with call
means we no longer
need the final step to call the function.
const myObj = {
name: 'My object'
};
const myLogger = {
name: 'My logger',
log: function () {
console.log(this.name);
}
};
myLogger.log.call(myObj);
The same value of My object
will be printed to the console.
As before it's also possible to pass an arbitrary number of params which get applied to the invoked method.
myObj.call(this, param1, param2, param3);
Apply
The final method I am going to focus on in this article is apply
. In fact this method is almost exactly identical as
call
apart from the optional extra parameters are replaced by a single array here.
myObj.apply(this, paramArray);
In the below example we have a MathHelper
object which allows us to calculate the total of a series of numbers. We can
use the apply
method to pass in an array of values as follows (we set the context to null
).
const MathHelper = {
total: function (...values) {
return values.reduce((acc, curr) => acc + curr, 0);
}
};
MathHelper.total.apply(null, [8, 37, 22, 5, 9]);
However, if you have used the spread operator (...
) before you would be correct in thinking that you could just do the
following also.
MathHelper.total(...[8, 37, 22, 5, 9]);
Or if you didn't have your values in an array format, then an arbitrary number of params would also work.
MathHelper.total(8, 37, 22, 5, 9);
Everyone one of the examples listed would give you the same value of 81
which is the sum of all the inputs.
Conclusion
apply
, bind
and call
can be very useful when sharing context between separate objects within javascript. Whilst
it's completely possible to go through your career without ever using them, I guarantee that if you use any
popular 3rd party libraries or frameworks that they will be making good use of them under-the-hood.
If anything it's worth spending a few minutes to refresh your memory, because you never know when you get this line of questioning sprung on you in a technical interview.