Writing Selfish JavaScript – Dealing with the this keyword

In class-based programming languages, the ‘this’ keyword is used to refer to the class instance within which the current method is defined. While JavaScript does provide an essential ‘this’ keyword which aims to serve a similar purpose, its functionality differs a bit and this can cause a lot of confusion.

A key difference between JavaScript and most other OO languages is that, in JavaScript there are no such things as classes and methods. All you have in JavaScript are objects and functions – While JavaScript does let you create objects which hold member functions (which look and behave very much like methods); they are not really methods. The main difference between a function and a method is that a method is bound to the instance of the class in which it is defined – A function is stand-alone and is bound to nothing…

If JavaScript does not support classes or methods, what does the ‘this’ keyword point to? The ‘this’ keyword in JavaScript actually points to the object within which the function is EXECUTED (as opposed to the object within which the function is DEFINED). This might seem like a small difference but the implications are huge. Because JavaScript lets you pass functions around as callbacks and assign them to other object’s properties, the object which contains a given function may change throughout your program execution and that is why the ‘this’ reference may also change depending on when your function is executed.

For example, take this code:

    var TypeOne = function () {
        this.foo = 'TypeOne foo';
        this.doFoo = function () {
            return this.foo;
        }
    }

    var TypeTwo = function () {
        this.foo = 'TypeTwo foo';
    }

    var t1 = new TypeOne();
    var t2 = new TypeTwo();
    t2.doFoo = t1.doFoo; // Copy the doFoo function from TypeOne object into TypeTwo object

    console.log(t1.doFoo()); // Outputs 'TypeOne foo'
    console.log(t2.doFoo());    // Outputs 'TypeTwo foo'

As you can see, the ‘this’ reference within the doFoo() function changes depending on the context within which the function is executed. In some cases, this feature may actually be desirable, but in many cases, this can be very problematic. Passing functions around in JavaScript is EXTREMELY common; in fact, that’s the entire premise of asynchronous programming – If we want to have some class-like behaviors in our code, there needs to be some way to bind a function to the object within which it is defined! Newer versions of JavaScript offer a useful ‘bind()’ function which lets you do just that, but unfortunately, this is a new feature and most browsers do not currently support it.

Ok, so what’s the solution then? Well, actually there are a number of solutions but I would like to discuss just one of them which I find to work consistently well, it’s easier to explain if I show some code first:

    var TypeOne = function () {
        var self = this;
        self.foo = 'TypeOne foo';
        self.doFoo = function () {
            return self.foo;
        }
    }

    var TypeTwo = function () {
        var self = this;
        self.foo = 'TypeTwo foo';
    }

    var t1 = new TypeOne();
    var t2 = new TypeTwo();
    t2.doFoo = t1.doFoo; // Copy the doFoo function from TypeOne object into TypeTwo object

    console.log(t1.doFoo()); // Outputs 'TypeOne foo'
    console.log(t2.doFoo());  // Outputs 'TypeOne foo'

Ok, so that works, but why? This trick is sometimes called ‘fixing the this’ because we are effectively capturing the ‘this’ reference at a convenient time and using it later when the actual ‘this’ keyword may have changed. This relates back to the fact that JavaScript determines the reference of ‘this’ upon function execution and not upon function definition – Here the variable ‘self’ is being assigned to ‘this’ when the constructor function is executed; at that point, ‘this’ is pointing to the newly created object (whose reference we will need to use within its member functions). What all this means is that when the doFoo() function is passed on to a TypeTwo object, it will still be using the ‘self’ reference from TypeOne. Using ‘self’ instead of ‘this’ in this way gives you certainty about the context within which the member functions will be executed.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s