This

Yeah that. Well sometimes you can set a variable to refer to "this" as "that", but "that" is another story.

When I was a Java programmer, it was easy to understand what "this" was. It was "this", a built in reference to the thing instantiated. Simple. Getting up to scratch with Javascript means understanding the finer details of the language (as well as the many quirks). What the "this" keyword (or the parameter "this") is bound to is one of those things.

There are five main things which "this" is bound to at call time (this call time point is important).

In Javascript, functions are "first class citizens" - objects that can be stored and passed as parameters (also referred to as Lambda). So we might think that if we use "this" in a function, "this" will refer to the current function, being as it is really an object. Well, think again. Just to confuse things, functions can be used as constructors that are used to create classes using the "new" keyword.

Constructor functions

Coming from a Java background it is pretty straight forward to know what "this" refers to when defining a class. When you create a new instance of the class "this" is bound to the object that was created. Similarly in Javascript.

var Car = function (make, model) {
  this.make = make;
  this.model = model;
};

Car.prototype.getMake = function () { return this.make; };

Only when a new object is created will "this" be bound to it. We do this using the "new" operator:

var myCar = new Car("Ford", "Mustang");

In the constructor, as it is now, we wouldn't know what "this" would be bound to because it hasn't been instantiated. We only know what "this" means because of the "." notation. Anything to the left of the dot will be "this".

As an aside, I think it is good to know exactly what is happening behind the scenes of a constructor function. Behind the scenes an object is created somewhat like the below:

var Car = function (make, model) {
  //var this = Object.create({});
  this.make = make;
  this.model = model;
  //return this;
};

The parameter in "Object.create({})" in this instance is just an object. If there was a prototype object defined that would be used as the parameter.

Method scope

Similar to constructor, say we have an object literal with a method "getName":

var man = {
   name: "Bob",
   getName: function () {
      return this.name;
   }
}

If you call man.getName() we can see that getName is a method on "man", so that will be the object that "this" is bound to. Just like before, JavaScript will come across the "this" keyword and work up the call stack. In this case it will see that to the left of the dot is the "man" object, so that would be bound to "this".

Global scope

So in JavaScript we can see that "this" needs to be bound to something. Assuming we run this in a Chrome console:

console.log(this);

"window : { ... " will be be returned if you are in a browser, or a whole lot of other code if you are running it in Node. The JavaScript engine will, as before, work up the call stack looking for what is bound to "this", but in this case there are no created objects so it will default to the global object.

Function scope

Function expression and function declaration work in a similar way as "global" when it comes to "this". For example:

var test = function () {
  console.log(this);
}
function test () {
  console.log(this);
}

Both of these will log whatever the global environment is. Even if these functions are declared within an object. That is a tricky one. It gets tricky when we consider something like this:

var topObject = {
 doSomething : function () {
  var doSubSomething = function () {
    console.log(this);
  }
  doSubSomething();
 }
}

Calling topObject.doSomething(); would log the global environment, not the context it is called in. This is because it is not a method, it is a function expression.

Call and Apply, parameter bound scope

So in these cases, the object you pass as the first parameter will be referenced to "this".

var man = {
   name: "Bob",
   getName: function () {
      return this.name;
   }
};

var man2 = { name : "Smithy" }

Calling man.getName.call(man2) would log "Smithy".

Bind

I said earlier there were 5 main ways that "this" is used. Bind kind of fits in with understanding "this". The function bind creates a new function with the context set to that which was passed in. "this" will refer to that context.

Now that's that.