Javascript Function Binding 
Published: 2020-06-29 07:04:58

Function binding is important because it defines the object on which a function will be called. Consider the example below:

 ````javascript
   const whereYat = "Outside";
 
   const mainObj = {
      whereYat: "Inside",
      find: function() {
         return whereYat;
      }
   };
 
   const otherObj = {
      whereYat: "Ain’t dere no more."
   };
 
   mainObj.find(); // “Outside”
 ```

There are three locations where something is named `whereYat`: a variable (`const`) declared on the global scope, a property of the object named `mainObj`, and a property of the object named `otherObj`. The function inside `mainObj`, when called, will return one of these `whereYat` values. As written, it will return `Outside`, since the function call is made on the global scope, where the variable `whereYat` lives. 

Intuitively, the purpose of this code snippet would appear to be different than its current result, but how does one take control of what value function `find` returns? The first thing our code needs would be keyword `this`:
 
````javascript
  const whereYat = "Outside";
 
   const mainObj = {
      whereYat: "Inside",
      find: function() {
         return this.whereYat;
      }
   };
 
   const otherObj = {
      whereYat: "Ain’t dere no more."
   };
 
   mainObj.find(); // “Inside”
 ```

Keyword `this` can lead to much confusion, but its use is necessary to prescribe exactly which object a function will operate on. The updated example is called “method invocation”, where `this` refers to the object on which the function (method) is called. A helpful tool is to look at what’s to the left of the dot at call time. This code returns the value of `whereYat` from inside `mainObj`. But what if we wanted the function to return the value of `whereYat` inside `otherObj`? Passing `otherObj` as an argument doesn't work because `this` is still bound to the object on which the method is called (the object to the left of the dot). Therefore, `mainObj.find(otherObj)` still returns `Inside`.

The keywords `.call()`, `.apply()`, and `.bind()` are helpful here, as they allow the function call to be applied to a passed-in object:

````javascript
  const whereYat = "Outside";
 
   const mainObj = {
      whereYat: "Inside",
      find: function() {
         return this.whereYat;
      }
   };
 
   const otherObj = {
      whereYat: "Ain’t dere no more."
   };
 
   mainObj.find.call(otherObj); // "Ain’t dere no more."
```

In the updated function call, the `.call()` method links keyword `this` to the argument object, `otherObj`. Using `.apply()` would give the same result here. But what happens if the function call is made with `.bind()`? 
````javascript
mainObj.find.bind(otherObj); // returns the actual find [function]
```
The string at `otherObj`'s `whereYat` key isn't returned because `.bind()` doesn't actually call the function like `.call()` (and `.apply()`). To return the value we're looking for, we would have to call the `.bind()` method immediately:
````javascript
mainObj.find.bind(otherObj)(); // "Ain’t dere no more."
```
This difference may make `.bind()` appear to be less useful. `.bind()`, howver, has a special capability `.call()` and `.apply()` don't have, which is to permanently "bind" the function to the argument object. 

````javascript
  const whereYat = "Outside";
 
   const mainObj = {
      whereYat: "Inside",
      find: function() {
         return this.whereYat;
      }
   };
 
   const otherObj = {
      whereYat: "Ain’t dere no more."
   };
 
   const bindToOther = mainObj.find.bind(otherObj); 
   bindToOther(); // "Ain’t dere no more."
```

By setting the `.bind()` method call to a variable (`bindToOther`), we've saved the connection between `otherObj` and the `mainObj.find` method. We can call this configuration anytime we want using the `bindToOther` variable name. For example, let's say we use `.call()` again to call the function on `mainObj`, returning `Inside`:
````javascript
   mainObj.find.call(mainObj); // “Inside”
```
We can go right back to the `bindToOther()` variable to once again return the result of calling the `find` method on `otherObj`:
````javascript
   bindToOther(); // "Ain’t dere no more."
```
This method of remembering specific function calls is useful not only in reducing code repetition, but also in reducing bugs that result from unintended function binding.