DEV Community

Annie Liao
Annie Liao

Posted on

Quick Guide to Call, Apply, Bind in JavaScript

Back in February, I created a quiz to help myself and others better understand the this keyword in JavaScript. At the time, I didn't delve into ways to explicitly determine what object this is referring to, i.e. using call, apply, and bind methods.

Fast forward to this week, I came across the call method when exploring the zooming effect of d3.js (a data visualization library):

svg.call(d3.zoom().on('zoom', () => {
  g.attr('transform', d3.event.transform)
}))
Enter fullscreen mode Exit fullscreen mode

As with any tools, it is easy to forget how to use them if you don't encounter them frequently. So here's a quick reference to all three methods as a reminder of their usage and differences.

Call() and Apply()

How They are Similar

Both call and apply methods allow us to specify what the this keyword should reference, and invoke the function immediately.

For instance:

function covidAlert() {
  alert(`To stop the spread, please ${this.outdoor}.`)
}

const measures = {
  indoor: 'wash your hands',
  outdoor: 'wear a mask',
  social: 'keep 6-feet distance'
}
Enter fullscreen mode Exit fullscreen mode

We cannot use measures.covidAlert() because measures object doesn't have covideAlert function as its execution context.

This is where the call or apply method comes to our rescue:

covidAlert.call(measures)
// or:
covidAlert.apply(measures)

// => To stop the spread, please wear a mask.
Enter fullscreen mode Exit fullscreen mode

How They are Different

If you want to pass arguments to the function, you can do so by passing in the arguments one by one using the call method.

function covidAlert(phaseNum, date, state) {
  alert(`To stop the spread, please ${this.outdoor}, so we can enter phase ${phaseNum} on ${date}. We are #${state}Smart.`)
}

const measures = {
  indoor: 'wash your hands',
  outdoor: 'wear a mask',
  social: 'keep 6-feet distance'
}

covidAlert.call(measures, 'four', 'July 20th', 'NewYork')
// => To stop the spread, please wear a mask, so we can enter phase four on July 20th. We are #NewYorkSmart.
Enter fullscreen mode Exit fullscreen mode

With apply, you should pass in an array of arguments, like so:

function covidAlert(phaseNum, date, state) {
  alert(`To stop the spread, please ${this.outdoor}, so we can enter phase ${phaseNum} on ${date}. We are #${state}Smart.`)
}

const measures = {
  indoor: 'wash your hands',
  outdoor: 'wear a mask',
  social: 'keep 6-feet distance'
}

const reopenDetails = ['four', 'July 20th', 'NewYork']

covidAlert.apply(measures, reopenDetails)
// => To stop the spread, please wear a mask, so we can enter phase four on July 20th. We are #NewYorkSmart.
Enter fullscreen mode Exit fullscreen mode

Bind()

The bind method is useful when you do NOT want to invoke the function immediately. Instead, bind creates a copy of the function that you can invoke later.

You can also pass in arguments with the bind method one by one, just like how you do it with call:

function covidAlert(phaseNum, date, state) {
  alert(`To stop the spread, please ${this.outdoor}, so we can enter phase ${phaseNum} on ${date}. We are #${state}Smart.`)
}

const measures = {
  indoor: 'wash your hands',
  outdoor: 'wear a mask',
  social: 'keep 6-feet distance'
}

const functionToBind = covidAlert.bind(measures, 'four', 'July 20th', 'NewYork')

functionToBind()
// => To stop the spread, please wear a mask, so we can enter phase four on July 20th. We are #NewYorkSmart.
Enter fullscreen mode Exit fullscreen mode

And that's a wrap! To learn more about the specifics of this keyword and its execution context in JavaScript, I recommend reading the following two articles. Their clear explanations and practical use cases really solidified my understanding of function binding:

Latest comments (2)

Collapse
 
functional_js profile image
Functional Javascript

Great explanation Annie.

As functional-programming-centric developer myself, I don't use these types of constructs.
I use a subset of the language to achieve all the goals that need to get accomplished, as performantly, robust, readable, and changeable as possible.

For example, ideally, I don't use...
bind
call
"this" keyword
"function" keyword
"class" keyword
"extends" keyword (inheritance)
interface classes
abstract classes
getters and setters
overloading
overriding
virtual methods
optional parameters
asynchronous callbacks
let (unless it's a value type that I will explicitly reassign)
implicit casts
implicit type checks
implicit null/undefined checks
single quotes
"require" keyword
polymorphic functions
recursion

Collapse
 
liaowow profile image
Annie Liao

Oh wow, thanks for listing all the constructs (helpers?) that can potentially create more headaches down the road. Indeed, I do recall running into issues with async callbacks. I also prefer using functional components in React.

While I'm still not experienced enough to choose between object-oriented and functional programming, your comment motivates me to reach that level soon :)