Javascript bind 101
Tags: javascript, bind, webdev, this
Published: 2019-11-23 14:06:38

---
title: Javascript bind 101
published: true
description: You are bound to use it eventually
tags: javascript, bind, webdev, this
canonical_url: https://irian.to/blogs/javascript-bind-101
---

`bind` is a common JS keyword. If you read enough JS code, you probably have seen it (`this.something = this.something.bind(this)` in React, anyone?). Whenever I see `bind`, I would get really confused. If this is you, by the end of this article you are bound (see what I did there 😎?) to understand `bind` much better!

**Warning**: knowledge of `this` is a prerequisite to understand bind. I wrote an [article](https://dev.to/iggredible/javascript-this-101-13j5) about `this`, check it out!

Bind has many applications and it would be impossible to cover in a short article like this, but I think the essentials are:
1. `bind` in a regular function
2. `bind`'s 2nd argument
3. `bind` in arrow function
4. `bind` in callback function


So what is bind? 

JS `bind` "binds" a function's `this` method with your value. It can also "bind" arguments.


# Bind in a regular function

What does it mean to bind a function's `this` method?

Recall that `this`, when called from inside a function, refer to an object where that function is called from.

```
const obj = {
  breakfast: 'pancakes',
  sayBreakfast(){
    console.log(`I had ${this.breakfast} for breakfast`)
  }
}

obj.sayBreakfast() // pancakes
```

With `bind`, we can bind sayBreakfast's `this` value to anything we want.

```
const waffles = obj.sayBreakfast.bind({breakfast: "waffles"})
waffles() // waffles
obj.sayBreakfast() // pancakes
```

# Bind's 2nd argument

Let's use an example of a regular function, inside an object, that takes an argument: 

```
const food = {
  entree: 'fried rice',
  sayLunch(appetizer) {
    console.log(`I  had ${appetizer} and ${this.entree} for lunch`)
  }
}

food.sayLunch('dumplings') // dumplings and fried rice
```

Let's bind it with sushi: 

```
const lunchie = food.sayLunch.bind({entree: 'sushi'})
lunchie() // undefined and sushi
```

Woops, we still need to pass an argument - otherwise it returns `undefined`, so let's do that:

```
lunchie('miso soup') // miso soup and sushi
```

Bind's 2nd argument can "lock" argument(s) values -  giving it pre-specified values.

```
const lunchy = food.sayLunch.bind({entree: 'tacos'}, 'chips')
lunchy() // chips and tacos
lunchy('burritos') // still chips and tacos
```

If you want to give a function pre-specified values but don't want to bind anything, put `null` as first argument.

```
const addStuff = function(first, second) {
  return first + second
}

addStuff(10,5) // 15
const addHundred = addStuff.bind(null, 100) // first is now 100
addHundred(3) // 103
addHundred(1,5) // 101
```

We bound the `first` argument to 100. Once bound, `first` will always be 100. Hence `addHundred(1,5)` is returning 101 and not 6. `1` becomes `second` argument and `5` is technically the third argument now.

# Bind in arrow function

This section assumes a lot of `this` knowledge. 

From my previous [article](https://dev.to/iggredible/javascript-this-101-13j5), I mentioned:

1. Only regular function and global function can have `this`.
2. Arrow function does not have `this` on its own
3. When `this` is referred to inside an arrow function, it will look up the scope to find this value. It behaves like lexical scope.

We will keep these in mind as we go through the last 2 sections.

Let's start by binding `{a: "rock"}` into `sayThis` arrow function.

```
const sayThis = () => console.log(this);
sayThis() // window obj
const imnotarock = sayThis.bind({a: "rock"})
imnotarock() // still window
```
It still returns window because arrow function does not have its own `this`. It looks up lexically for either regular function or global object's `this`. 

This would have worked fine on regular function:

```
const sayThisAgain = function(){console.log(this)}
const imarock = sayThisAgain.bind({a: "rock"})
imarock() // {a: "rock"}
```

Although we can't bind `this`, we can give an arrow function pre-specified values.

```
const addFive = (x) => x + 5
addFive(10) // 15
const gimmeSeven = addFive.bind(null, 2)
gimmeSeven() // 7
gimmeSeven(10) // still 7
```

# Bind in callback function

Let's say we have a `sayDinner()` regular function, inside dinner object, using `reduce()`:

```
let dinner = {
  meals: ['pizza', 'pie', 'tea'],
  sayDinner() {
    let food = this.meals.reduce(function(acc, currentEl){
      if(currentEl === this.meals.slice(-1)[0]){
        return `${acc} ${currentEl}!`
      }
      return `${acc} ${currentEl},`
    }.bind(this), "")
    console.log(food)
  }
}

dinner.sayDinner() // pizza, pie, tea!
```

*(Btw, if you are not familiar with reduce, check [this](https://dev.to/iggredible/javascript-reduce-101-563g) out)*

Pay attention at `.bind(this)` at the end of our reducer function. The bind is necessary to give `this.meals` context. 

Let me explain:

When the callback function is called, it has no idea what `this.meals` (the one inside reducer function that is being sliced) is. It does not even know that `dinner` object exists. It only knows `acc` and `currentEl`. When we do `.bind(this)`, we are telling the reducer, "Hey, if you see `this.meal` inside yourself, you can use `dinner`'s `meals`." 

Try the above again without `.bind(this)`

```
dinner = {
  meals: ['pizza', 'pie', 'tea'],
  sayDinner() {
    let food = this.meals.reduce(function(acc, currentEl){
      if(currentEl === this.meals.slice(-1)[0]){ // does not know about this.meals if we don't bind it
        return `${acc} ${currentEl}!`
      }
      return `${acc} ${currentEl},`
    }, "")
    console.log(food)
  }
}
dinner.sayDinner() // error
```

This gives an error `"Cannot read property 'slice' of undefined"` because `this.meals` inside our callback function is undefined if not bound.

Retrospectively, let's replace our callback function from regular function into arrow function. It works perfectly without `bind`:

```
dinner = {
  meals: ['pizza', 'pie', 'tea'],
  sayDinner() {
    let food = this.meals.reduce((acc, currentEl) => {
      if(currentEl === this.meals.slice(-1)[0]){ 
        return `${acc} ${currentEl}!`
      }
      return `${acc} ${currentEl},`
    }, "")
    console.log(food)
  }
}

dinner.sayDinner() // pizza, pie, tea!
```

Recall three things about `this` and arrow function mentioned above.

In this case, our reducer arrow function, seeing `this.meals` inside itself and does not know what it means, lexically looks up at `sayDinner()` function. Since `sayDinner()` **is** a regular function, it **does** have `this.meals` context.

What if we change `sayDinner()` from regular to arrow function?

Something like this:

```
dinner = {
  meals: ['pizza', 'pie', 'tea'],
  sayDinner: () => {
    let food = this.meals.reduce((acc, currentEl) => {
      if(currentEl === this.meals.slice(-1)[0]){
        return `${acc} ${currentEl}!`
      }
      return `${acc} ${currentEl},`
    }, "")
    console.log(food)
  }
}

```

Let's think: we are inside reducer function trying to get `this.meals`. Recall our three rules above, rule #2: arrow function does not have `this` on its own, so it will look for regular function or object that has `this.meals`. The next object it checks is global window object, but it finds none. It throws an error: `"Uncaught TypeError: Cannot read property 'reduce' of undefined"`


Of course, we can always define a global `meals`, like

```
window.meals = ['Hamburger', 'Fries']
const dinner = {...}

dinner.sayDinner() // hamburger, fries
```

And it would have worked just fine :)


There you have it folks! Javascript `bind`. Now go bind stuff!!!


# More Readings/ Resources

* [Understanding This, Bind, Call, and Apply in JavaScript](https://dev.to/digitalocean/understanding-this-bind-call-and-apply-in-javascript-dla)
* [Understanding the "this" keyword, call, apply, and bind in JavaScript](https://tylermcginnis.com/this-keyword-call-apply-bind-javascript/)
* [What is the use of the JavaScript 'bind' method?](https://stackoverflow.com/questions/2236747/what-is-the-use-of-the-javascript-bind-method)
* [how to replace `bind(this)` in es6](https://stackoverflow.com/questions/48695434/how-to-replace-bindthis-in-es6)
* [Can you bind arrow functions?](https://stackoverflow.com/questions/33308121/can-you-bind-arrow-functions)