JavaScript Prototype Instantiation

In JavaScript, functions can be used in two ways; they can be simply called or they can be instantiated. When you call a function, it will simply run the code inside it and possibly return some value – When you instantiate a function, the JavaScript engine will first create a new object (a clone of that function’s prototype) and then will call that function using the newly created object as the context for the ‘this’ keyword.

Function prototypes are essentially empty objects by default – You can add properties to the prototype object using the Function.prototype property. Here is an example of how to add properties to a function’s prototype:

var Fun = function() {
    this.prop = 'This is a property of a Fun instance';
}

// Adding a 'foo' property to the 'Fun' function’s prototype
Fun.prototype.foo = function() {
    return 'foo';
}

var fun = new Fun(); // fun is an object with a 'foo' property which is a function

When ‘new Fun()’ is called, the JavaScript engine first creates a clone of the function’s prototype object which essentially looks like this: {foo: function() {return ‘foo’;}}; then it executes the Fun function using the cloned object as the ‘this’ reference – Because of that, properties added to ‘this’ within the function body can overwrite those defined in the prototype.

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.