A quick and dirty guide to the call, apply, and bind methods
Tags: javascript, webdev, jsfundamentals
Published: 2019-05-20 00:41:25

---
title: A quick and dirty guide to the call, apply, and bind methods
published: true
description: `call`, `apply` and `bind` make us less subject to the cruel whims of the this keyword. 
tags: JavaScript, web development, JS fundamentals
---

***High-level summary for the bosses:*** `call`, `apply` and `bind` are methods we can call on functions to make us less subject to the cruel whims of the `this` keyword. 
<hr />

If you're in the UK and you tell someone to take the lift to the second floor, they'll know you're talking about using the machine that transports people between different floors of a building. In the US, someone hearing the same instruction might initially think someone is about to give them a piggyback ride up a flight of stairs. 

The same is true when writing code — reserved keywords have different meanings depending on the scope, or execution context, in which they're used. In JavaScript, one of the trickiest examples of a keyword that changes its meaning at the drop of a hat is `this`.

**What is `this`?** 
The `this` keyword is a pointer that refers to a scope, or execution context, in your program. Which scope it refers to depends on where it is used. When used outside of a declared object, `this` points to the global object. (In the browser, the global object is actually the `window` object. If you open up the console in the inspector and type `console.log(this)`, you will see the `window` object and all of its properties and methods logged). 

Used inside of a declared object, `this` refers to the closest parent object. For example:
```
    const jim = {
      name: "Jim",
      age: 24,
      printAge: function() {
    	return this.age
      }
    }
    
    const bob = {
      name: "Bob",
      age: 35,
      printAge: function() {
         return this.age
      }
    }
    
    jim.printAge() // returns 24
    bob.printAge() // returns 35
```

Like the rest of us, Jim is getting older. Let's add another method to the `jim` object that will take the number of years he has aged, and return his new age:

    const jim = {
      name: "Jim",
      age: 24,
      printAge: function() {
    	return this.age
      },
      increaseAge: function increaseAge(years){
    		return this.name + " is now " + (this.age + years) + " years old."
    	}
    }
    
    const bob = {
      name: "Bob",
      age: 35,
      printAge: function() {
         return this.age
      }
    }

When we call `jim.increaseAge(5)`, it will return `Jim is now 29 years old`. But what if we want to use this same method on the `bob` object? We could write it out again inside of `bob`, but that would be redundant. Instead, we'll use some trickery to redefine `this` when we call `increaseAge` so that it refers to the `bob` object, and the `name` and `age` properties therein. 

**`call` to the rescue**
`call` is a method that we can use to specify what the keyword `this` refers to in the function to which we're adding it. The first argument that we pass into `call` is known as the `thisArg`. This is the object we want `this` in the function to refer to. The subsequent arguments are simply the regular arguments that we want to pass into the function. 

Using `call`, we can access the properties and methods of the `bob` object when we invoke `jim.increaseAge`:

    const jim = {
      name: "Jim",
      age: 24,
      printAge: function() {
    	return this.age
      },
      increaseAge: function increaseAge(years){
    		return this.name + " is now " + (this.age + years) + " years old."
    	}
    }
    
    const bob = {
      name: "Bob",
      age: 35,
      printAge: function() {
         return this.age
      }
    }
    
    jim.increaseAge.call(bob, 5) // returns "Bob is now 40 years old."

`apply` allows us to control what `this` refers to inside of a function when we call it from outside of the context in which that function was defined. This is the sort of sorcery that allows us to write more versatile and reusable code.

**`apply` is `call`'s slightly higher achieving older sibling**
Like `call`, `apply` specifies the context that `this` in the function will take in its first argument (the `thisArg`). `call` can only pass a predetermined number of arguments to a function, however, whereas `apply` passes an array of arguments to a function that are then unpacked and passed as parameters to the function.

Let's take a look at how this works: 

    const obj1 = {
    	num: 5
    }
    
    const obj2 = {
    	num: 2
    }
    
    const addToObj = function(a, b, c) {
    	return this.num + a + b + c
    }
    
    let arr1 = [2, 3, 5, 6]
    let arr2 = [4, 6, 3, 9]
    
    console.log(addToObj.apply(obj1, arr1)) // logs 15 to the console
    
    console.log(addToObj.apply(obj1, arr2)) // logs 18 to the console
    
    console.log(addToObj.apply(obj2, arr1)) // logs 12 to the console
    
    console.log(addToObj.apply(obj2, arr2)) // logs 15 to the console

Above, we declare arrays as variables then use these variables as `apply`'s second argument to pass them into the function as separate parameters. With `call`, we would not be able to do this, as `call` requires the functions arguments to be passed as regular comma-separated parameters. 

**The `bind` method: delayed gratification**
`bind` is the third in this family of methods that allow us to redefine the context of `this` when we call functions. While the difference between `call` and `apply` is subtle, the difference between `bind` and `call` and `apply` is more significant. 

Rather than immediately invoking the function on which it's called, `bind` returns a function definition with the keyword `this` set to the value of the first argument passed into it (the `thisArg`). This is very useful when we know we want to redefine `this` in a function, but we don't know which arguments we want to pass into the function. 

Let's go back to `bob` and `jim` to take a look at how `bind` works: 

    var bob = {
       firstName: "Bob",
       sayHi: function(){
          return "Hi " + this.firstName
       },
       addNumbers: function(a,b,c,d){
          return this.firstName + " just calculated " + (a+b+c+d)
       }
    }
    
    var jim = {
       firstName: "Jim"
    }
    
    var jimAdd = bob.addNumbers.bind(jim, 1, 2, 3, 4)
    
    jimAdd() // Jimm just calculated 10

Here, we took the method `addNumbers` on the `bob` object and called the `bind`  method on it to create another function in which `this` is redefined as the `jim` object. We stored this new function in the variable `jimAdd`, then subsequently called `jimAdd`. This works, because unlike `call` and `apply`, `bind` doesn't immediately invoke the function it's used on. 

**Don't know your arguments yet? Get out of your bind with `bind`.** 
When we use `bind`, we do not always need to know the parameters to the function we are creating — the only argument we need to pass into `bind` is the `thisArg`. 

Let's return once again to Jim and Bob:

    var bob = {
       firstName: "Bob",
       sayHi: function(){
          return "Hi " + this.firstName
       },
       addNumbers: function(a,b,c,d){
          return this.firstName + " just calculated " + (a+b+c+d)
       }
    }
    
    var jim = {
       firstName: "Jim"
    }
    
    var jimAdd2 = bob.addNumbers.bind(jim, 1,2)
    jimAdd2(3,7) // returns 'Jim just added 13'

When we create the `jimAdd2` function with `bind`, we only pass two arguments into the function. When we call it on the following line, we pass two additional arguments, and the function is called with all four arguments. 

**Using `bind` with asynchronous code:** 
Another common application of the `bind` method is is asynchronous code. 

    var bob = {
       firstName: "Bob",
       sayHi: function(){
    	  setTimeout(function(){
    		console.log("Hi " + this.firstName)
    	  },1000)
       }
    }
    
    bob.sayHi() // Hi undefined (1000 miliseconds later)

Since the closest parent object to the `sayHi` method is `bob`, it would make sense that `sayHi` returns `Hi Bob`. However, because `setTimeout` is called at a later point in time, the object that it is attached to at the point of execution is not the `bob` object, but the `window` object.  

If we still want the context of `this` in the `setTimeout` function to be the `bob` object when it is called, `bind` provides a perfect solution. It allows us to explicitly set the context of `this` without immediately invoking the function:

    var bob = {
       firstName: "Bob",
       sayHi: function(){
          setTimeout(function(){
             console.log("Hi " + this.firstName)
         }.bind(this),1000)
       }
    }
    
    bob.sayHi() // "Hi Bob"

In this example, we can actually pass `this` in as the `thisArg` of `bind` on the `setTimeout` function, because in this case, `this` is equal to the `bob` object itself. (We could just as easily have passed in `bob`, but often, we will see code that uses `this` in cases such as this instead of the name of the object.