Gonna explore where this can go wrong by using a series of scenarios.

Scene 1: Passing a function that uses this as a callback function

Imagine a view with a button. The button has an id of yoke and jQuery is being used.

var bizarre = {
  subject: 'Yo mama',
  joke: 'got an afro with a chin strap',
  makeJoke: function() {
    return this.subject + ' ' + this.joke;
  }
};

var button = $('#yoke');
button.click(bizarre.makeJoke); // undefined

Soooooo I expected a joke, but got undefined. In this scenario, the invoker is button, so this is set to the jQuery wrapped object. I’m certain this jQuery object does not have subject or joke properties…

One way of fixing the context of this for this scenario is to use the bind() method to hardcode the value of this inside bizarre.makeJoke() like so:

var bizarre = {
  subject: 'Yo mama',
  joke: 'got an afro with a chin strap',
  makeJoke: function() {
    return this.subject + ' ' + this.joke;
  }
};

var button = $('#yoke');
button.click(bizarre.makeJoke.bind(bizarre)); // Yo mama got an afro with a chin strap

Scene 2: Using this inside a closure

var momo = {
  name: 'momo',
  friends: [
    {name: 'red', age: 17, favoriteColor: 'red'},
    {name: 'erica', age: 17, favoriteColor: 'green'}
  ],
  hasKnife: true,
  callback: function() {
    console.log(this.name); // momo
    console.log(this.hasKnife); // true (oh shit)
    this.friends.forEach(function(friend) {
      console.log(this); // [object Window];
      console.log('Friend of ' + this.name); // Friend of undefined
      console.log(friend.name + ' is ' + friend.age + ' years old and likes ' + friend.favoriteColor);
      // Red is 17 years old and likes red
      // Erica is 17 years old and likes green
    });
  }
};

momo.callback();

What happened to Momo? Inside the forEach method, an anonymous function was passed as the callback. This anonymous function cannot access its parent function’s this. This issue can be addressed by saving the parent function’s this to a local variable that is still accessible by the anonymous function.

var momo = {
  name: 'momo',
  friends: [
    {name: 'red', age: 17, favoriteColor: 'red'},
    {name: 'erica', age: 17, favoriteColor: 'green'}
  ],
  hasKnife: true,
  callback: function() {
    console.log(this.name); // momo
    console.log(this.hasKnife); // true (oh shit)
    var self = this; // boom shakalaka
    this.friends.forEach(function(friend) {
      console.log(this); // [object Window];
      console.log('Friend of ' + self.name); // Friend of momo
      console.log(friend.name + ' is ' + friend.age + ' years old and likes ' + friend.favoriteColor);
      // Red is 17 years old and likes red
      // Erica is 17 years old and likes green
    });
  }
};

momo.callback();