Back

JavaScript Fundamentals - call, apply, bind

Before we jump in to what call(), apply() or bind() it’s important to understand what this is in JavaScript. Every function in Javascript while executing has a reference to the its current execution context, which is called “this”. (Ok, not every function, ES6 arrow functions are the exception).

How is this determined?

Kyle Simpson, in his Deep Javascript Foundations course on Frontend Masters, repeats this phrase over and over:

The only thing that matters is how the function was called

Now, this (no, not this) is where call(), apply() and bind() come in. When you use any of these methods, you are explicitly telling JavaScript what this should refer to when the function is called. If you are calling the function with any of those three methods, then you are explicitly telling JavaScript what this should refer to.

The other two ways that this is determined is either by the implicit binding rule, or the default rule (the global object is set to this). Implicit binding looks like this:

function sayMyName() {
  console.log(`Hi, ${this.name}!`)
}
var beyonce = { name: 'Beyonce', sayMyName }
beyonce.sayMyName() // Hi, Beyonce!

In this code, this refers to the object beyonce. JavaScript implicitly used the object from where the function it was called as this.

Now, let’s look at how to explicitly tell JavaScript what this refers to:

Why or when would you use call, apply or bind

When you use call() or apply() , the function is invoked immediately, but if you use bind() then you’re setting what this points to when the function is eventually invoked.

Here’s my summary of what each of them do:

call()

Plain english: with this function, run it immediately and use the first parameter I give you as the object that this should refer to within that function. The following parameters that I give you (comma separated) should be used for the remaining parameters needed for the function.

Example code:

var cat = { name: 'Gigi', hunger: 10 }
function feedTheCat(foodType, amount) {
  this.hunger -= amount
  console.log(
    `${this.name} is well fed with some ${foodType} food. 
      Hunger level is now ${this.hunger}`
  )
}
feedTheCat.call(cat, 'wet', 5)
// Output:
// Gigi is well fed with some wet food. Hunger level is now 5

The above code in plain english: I have a cat whose name is Gigi and hunger level is 10 (line 1). Here’s a function that feeds the cat. The function first reduces the hunger level of the cat by the amount passed in to the function. Then console.log the cat’s name, the type of food and the new hunger level.

Lastly, for the function feedTheCat invoke the function with cat set as the this parameter, use wet as the foodType and the amount as 5.

apply()

Plain english: with this function, run it immediately and use the first parameter I give you as the object that this should refer to within that function. The following parameters that I give you (in an array) should be used for the remaining parameters needed for the function.

Example:

var cat = { name: 'Gigi', hunger: 10 }
function feedTheCat(foodType, amount) {
  this.hunger -= amount
  console.log(
    `${this.name} is well fed with some ${foodType} food. Hunger level is now ${
      this.hunger
    }`
  )
}
feedTheCat.apply(cat, ['wet', 5])
// Output: Gigi is well fed with some wet food. Hunger level is now 5

The above code in plain english: same as call() except this time, use the values within the array for the function parameters, rather than a comma-separated list.

bind()

Plain english: For this function, set the value of this to the first parameter that I give you, but don’t execute it yet!

Example:

var cat = { name: 'Gigi', hunger: 10 }
function feedTheCat(foodType, amount) {
  this.hunger -= amount
  console.log(
    `${this.name} is well fed with some ${foodType} food. Hunger level is now ${
      this.hunger
    }`
  )
}
feedTheCat.bind(cat)('wet', 5)
// Output: Gigi is well fed with some wet food. Hunger level is now 5

The above code in plain english: first bind this to cat for the function feedTheCat. Now, call the function with the following parameters ”wet”, 5.

You could also pass in the function parameters comma-separated, like this:

feedTheCat.bind(cat, 'wet', 5)()

Typically, when you use bind you would create a new bounded function and then call the function later, something like this:

var gigi = { name: 'Gigi', hunger: 10 }
var oliver = { name: 'Oliver', hunger: 5 }
var feedTheCatGigi = feedTheCat.bind(gigi)
var feedTheCatOliver = feedTheCat.bind(oliver)
feedTheCatGigi('wet', 5)
feedTheCatOliver('dry', 5)

That way you can change the value of this for different objects.

call() and apply() are very similar, except that apply() accepts the arguments for the function as an array.

So if I were to rename apply() to be much more descriptive of what it actually does, I would rename it to callUsingArrayOfValues() , but that’s a mouthfuls, so we’ll stick with apply().

I think I get tripped up on it because bind() doesn’t invoke the function, so I would assume that a similar word like apply() wouldn’t invoke it either. Just remember that bind() doesn’t invoke the function, but the other two do.

In short:

  • call() explicitly binds this, function parameters are passed in comma-separated. Function is immediately invoked.
  • apply() same as call() except function parameters are passed in as an array
  • bind() explicitly binds this for the function, but the function is NOT immediately invoked.
Published 28 Aug 2018

Front-end web developer. Civic tech hacker. San Francisco Bay Area.
Jeff Appareti on Twitter