Skip ahead!

Bind is a magical little method attached to the prototype of functions in Javascript. It is used to bind a host class to a method that you are passing in to another function, meaning that the value of the keyword this will change depending on what is bound to the function.

This article presumes a working knowledge of this. If you’re unfamiliar, you can learn all about it here.

Anonymous callbacks

In Javascript, functions can be passed as a parameter to another function. Let’s take a look at an example:

document.addEventListener('click', (event) => {
  console.log(event.target);
});

With our event listener, we pass a callback function. This callback function is stored internally inside the document object, and is then called upon when a click event on the document occurs. The target of the click event will be logged to the console.

Named callbacks

Similarly, we could also pass the function like this:

function onClick(event) {
  console.log(event.target);
}

document.addEventListener('click', onClick);

In this instance, we just define a named function and pass it in, instead of an un-named arrow function. Sometimes we may want to do this to better document our code (with named functions), or just when the logic becomes a bit cluttered.

We need more class!

However, what if we were dealing with classes?

class Application {
  clickCounter = 0;

  constructor() {
    document.addEventListener('click', this.onClick);
  }

  onClick(event) {
    console.log(event.target);
    this.clickCounter++;
  }
}

In the example above, we will again log the target of the click event. After that, we will increase a counter that we store within our class. Do we think this will work?

Unfortunately, it won’t.

Why? I hear you ask. Well, it all lies with the usage of this - more specifically when we call this.clickCounter++.

When we use this, we are referencing the data held within the class that this method is being called in. When we pass our callback in to the event listener, it is then being called within the document class, which actually binds this to event.target, but that’s for another article altogether. Unfortunately for us, this means that clickCounter does not exist when we try to increment it.

Bind it!

How can we solve this, you ask? Well, that’s where bind comes in to play.

class Application {
  clickCounter = 0;

  constructor() {
    document.addEventListener('click', this.onClick.bind(this));
  }

  onClick(event) {
    console.log(event.target);
    this.clickCounter++;
  }
}

When we use .bind(this), we are saying “When you call this function, make sure it remembers where it comes from - this class is its home”

When this method is now called, no matter where it is called from, it will refer back its original parent class whenever it tries to access this, therefore incrementing our clickCounter as expected.

So, if we run this now, it will work as we expect! Of course, there are other applications of bind, such as binding a separate class instance. However, this is much less common and rare to find.

I hope this small article helps you on your way to understanding the inner depths and quirks of JavaScript!