Carl Willimott - Tech Blog: The ABC of javascript

The ABC of javascript

October 04, 2022

5 min read

Back

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.