Friday, July 30, 2021

Call, Apply and Bind in Javascript


In Javascript call(), apply(), and bind() are all methods of Function objects. A Function object is automatically created for you when you define a function in your code. If your function is named "calculateTax" then you can call the method calculateTax.bind(), or calculateTax.apply(), or calculateTax.call().

So what good are these methods?

They allow you to control how 'this' is set when the function is invoked.

I'll focus on bind() since that's the one I use most commonly.

When you call yourFunction.bind(someObject), it will return a new version of the function where the 'this' parameter will be bound to whatever object you specify as the parameter (someObject in this case). Here's an example:

// Controller Class:
class ShoppingCartController {
  constructor() {
    this.total = 0;
    this.taxRate = 0.08;
    // Create a new version of calculateTax where 'this'
    // will be bound to the ShoppingCart object (this).
    this.calcTax = this.calculateTax.bind(this);
  }
  
  setTotal(total) {
    this.total = total;
  }
  
  calculateTax(req, res) {
    this.tax = this.total * this.taxRate;
    res.json({tax: this.tax});
  }
}
export new ShoppingCartController();

// In Express Router File:
let shoppingCart = require('../controllers/ShoppingCart')

// Note: using shoppingCart.calculateTax would not work.
router.get('calctax', shoppingCart.calcTax); 

This is a Node/Express application where there is a ShoppingCart controller. We want to make it so that a particular route calculates and returns the tax. In the route.get() call, if we use shoppingCart.calculateTax, it will not work because 'this' will not be set correctly when the method executes. However, if we use the calcTax() method, 'this' will be set to point to the ShoppingCartController object and the method will be able to compute the tax.

Bind is essiential when you have a method of an object that you want to use as a callback function. The code that invokes the callback (e.g. the Express Router in this case) doesn't know how 'this' should be set. It just calls the callback function it's given. In this situation - since we've called bind() ahead of time - the code that executes the callback can simply call the function without worrying about how 'this' will be set. We've already bound 'this' to the appropriate object.

Image Credit: Wikimedia, CC-BY-SA 2.0

Post a Comment

Note: Only a member of this blog may post a comment.