December 12, 2014

Javascript bind vs call

bind and call take same arguments, but do different things. call simply allows you to execute a function in a specific scope and returns the result of running that function. bind actually returns a new function locked to the scope passed in, and you may execute it as many times as you want.

Here’s an example. Try running it in your browser’s JS console to see the results for yourself.

// create an object with its own scope to work with
var Hat = function (size) {
  this.size = size;
  console.log("hat object created");
};

// and another object to compare it to
var Shirt = function (size) {
  this.size = size;
  console.log("shirt object created");
};

// this function returns the value of "size" in whatever scope it runs in
var getSize = function () {
  return this.size;
};

var size = "I don't know";
var hat = new Hat("M");
var shirt = new Shirt("XL");

// getSize() usually returns the global value for size
console.log("getSize in global scope:", getSize());

// here's an example of running it in scope of hat once
console.log("getSize in `hat` scope:", getSize.call(hat)); // writes out 'M'

// run it regularily, and it is back to the global scope
console.log("getSize in global scope again:", getSize()); // writes out 'I don't know'

// now make a new version of getSize() that only runs in the scope of hat
var getHatSize = getSize.bind(hat);

// writes out 'M' every time!
console.log("getHatSize:", getHatSize());
console.log("getHatSize again:", getHatSize());

// what if getHatSize is added to shirt's prototyp?
Shirt.prototype.getHatSize = getHatSize;
console.log("getHatSize added to shirt's prototype", shirt.getHatSize()); // writes out 'M', so the binding to the scope of hat has not been broken

// meanwhile, adding getSize
Shirt.prototype.getSize = getSize;
console.log("getSize added to shirt's prototype:", shirt.getSize()); // writes out 'XL', which means the function is executing in the scope of the shirt object