Better JavaScript–What is this?

JavaScript has quite a few ways of using the this keyword, but it’s not really that difficult to know what this means in the different contexts.  Let’s take a look at the different meanings of this.

The Different Meanings of this

window.name = "Global object";

function justSomeFunction(a, b, c) {
    console.log(this.name);
    return "Just some function";
}

var justSomeObject = {
    name : "Just some object",
    method : justSomeFunction
}

var justSomeOtherObject = {
    name : "Just some OTHER object"
}

function functionWithConstructor(a) {
    this.name = "New object instance " + a;
}

Here I am creating a few different contexts and naming all of them.  So let’s do some testing.

console.log(this.name);  // Global object

So by default this refers to the global object.

justSomeFunction(1, 2, 3);  // Global object

When calling a function this also refers to the global object.

justSomeObject.method();  // Just some object

When calling a method this refers to the object the method belongs to.

var a = new functionWithConstructor("a");
var b = new functionWithConstructor("b");
console.log(a.name);  // New object instance a
console.log(b.name);  // New object instance b

When using the new keyword to create a new object this refers to the newly created object.

Explicitly setting this

justSomeFunction.apply(justSomeOtherObject, [1, 2, 3]);  // "Just some OTHER object"
justSomeFunction.call(justSomeOtherObject, 1, 2, 3);  // "Just some OTHER object"

Instead of executing the function here we are using the apply and call methods on Function.prototype.  When using these methods the value of this will be set to the first argument passed to the method.  This is often used in frameworks so you can reliably use this and know what to expect.  Both these methods do the same thing, they just pass arguments in a slightly different way.

justSomeObject.method.apply(justSomeOtherObject, [1, 2, 3]);  // "Just some OTHER object"
justSomeObject.method.call(justSomeOtherObject, 1, 2, 3);  // "Just some OTHER object"

So we can even change the value of this for method calls!

There be dragons

Let’s look at two scenarios which can often cause headaches.

var yetAnotherObject = {
    name : "Yet another object"
}

yetAnotherObject.anotherMethod = function() {
    function subFunction() {
        console.log(this.name);
    }            
    subFunction();
}
yetAnotherObject.anotherMethod();  // Global object

You would probably expect this inside of subFunction to refer to yetAnotherObject, but it doesn’t.  This is apparently considered to be a design flaw in JavaScript, mostly because it has pretty much no practical use.

function justSomeFunction(a, b, c) {
    console.log(this.name);
    return "Just some function";
}

var justSomeObject = {
    name : "Just some object",
    method : justSomeFunction
}
justSomeObject.method();  // Just some object

var methodOnJustSomeObject = justSomeObject.method;
methodOnJustSomeObject();  // Global object

So method aliasing doesn’t really work as you expect, but it also means that when we assign a method to an object this will work as expected.

A lot of credit for the info here goes to JavaScript Garden – a truly excellent site.

I hope this has been interesting.  (C’mon – tell me you didn’t see that coming)  Happy coding.