JavaScript this, self, bind, call, and apply

Last Updated on April 3, 2016

When a function is set and the this value is not assigned, it is always the window object. It can change depending on where the function is invoked.


console.log(this); // Window
function f1() {
  console.log(this); // Window
}
f1();
var f2 = function() {
  console.log(this); // Window
}

The quirk is, why does javascript set the this value of a function, within a function within an object to the window object?


var o = {
  name: "Peter",
  myFunc: function() {
    this.name = "John";
    console.log(this);
    var setname = function(newname) {
      this.name = newname;
    }
    setname("Updated to Jim");
    console.log(this); // Not changed
  },
}
o.myFunc();

How do we deal with it? The self pattern: var self = this;
But before that let’s look at what a function contains.

  1. A function contains properties:
    1. name property (can be anonymous)
    2. code property (invocalble “( )”
  2. Every function also contains three special methods
    1. call
    2. bind
    3. apply

Here is an example of the self pattern.


var o = {
  name: "Peter",
  myFunc: function() {
    var self = this; // The magic line
    self.name = "John";
    console.log(self);
    var setname = function(newname) {
      self.name = newname;
    }
    setname("Updated to Jim");
    console.log(self); // Without the self pattern this would remain "John"
  },
}
o.myFunc();

.bind, .call() and .apply() are accessed by using the dot notation.

.bind creates a copy of the function you are calling, and passes the object you want to be the this property.


var car = {
  make: "Honda",
  model: "Pilot",
  year: "2013",
  carInfo: function() {
    var info =  this.year + ", " + this.make + " " + this.model;
    return info;
  }
}
var displayInfo = function(color, weight) {
  console.log("The info is: " + this.carInfo() + " " + color + " " + weight);
}

var showCarInfo = displayInfo.bind(car);
showCarInfo(); 
//-------------------------

displayInfo.call(car, "white", "10,000 lbs");
displayInfo.apply(car, ["white", "10,000 lbs"]);

With .call() and apply() you are not making a copy – you are invoking the function directly and passing it’s this property with parameters – .apply() requires an array of parameters and .call() requires a list.

Since .bind() is creating a copy of the function, you have some useful patterns at your disposal – function borrowing, and function currying.


//-------------------------
// Function Borrowing
var car2 = {
  make: "Chevy",
  model: "Traverse",
  year: "2016",
}
console.log(car.carInfo.apply(car2) );

//-------------------------
// Function Currying
function multiply(a,b) {
  return a*b;
}
var multiplyByTwo = multiply.bind(this, 2);
console.log( multiplyByTwo(4) );

var multiplyByThree = multiply.bind(this, 3);
console.log( multiplyByThree(4) );