30 May 2014

What's THIS? (In Javascript) - PART I

In Javascript the value of "this" depends on the invocation pattern used.
In Javascript we have 1 invocation operator (), but 4 invocation patterns.


The method invocation pattern
We can define a function as a property of an object, in that case we call that function a method. We use the method invocation pattern when we invoke a method on an object with the dot syntax. In the method invocation pattern "this" points to the object whose method has been invoked. "This" is set at execution-time only (late-binding), that is, when the method is actually invoked. The invoked method has access to the object properties via "this". An example:

var myWonderfulObject = {
    importantProperty: "Hello",
    importantMethod: function(salutation) {
        this.importantProperty = salutation;
        alert(this.importantProperty);
    }
};

myWonderfulObject.importantMethod("Farewell"); //Method invocation: "Farewell"

The function invocation pattern
When we invoke a function (thus, not an object property, e.g.:  var res = mul(2, 3);), then "this" is always set to the global object. That is bad in the case of inner functions invocation, and it's a bug in the language design. That makes an inner function inside a method unable to access the object's properties. Let's see an example:

var myWonderfulObject = {
    importantProperty: "Hello",
    importantValue: 2,
    importantMethod: function(salutation) {
        this.importantProperty = salutation;
    },
    displayTripledImportantValue: function() {
        function tripleImportantValue() {  //Inner function
            this.importantValue = this.importantValue * 3;
        }
        tripleImportantValue();  //Inner function invocation
        alert(this.importantValue);
    }
};

myWonderfulObject.displayTripledImportantValue(); //BUG: It wrongly alerts 2 !!


But there's a simple fix (an "hack" somebody would say), in the method before calling the inner function we define var that = this; thus the inner function can access "this" via "that" :)
Here's the fixed code:

var myWonderfulObject = {
    importantProperty: "Hello",
    importantValue: 2,
    importantMethod: function(salutation) {
        this.importantProperty = salutation;
    },
    displayTripledImportantValue: function() {

        //Fix!! ("that" is a just convention we can use whatever name we like).
        var that = this;

        function tripleImportantValue() {

            // Accessing "this" via "that" :)
            that.importantValue = that.importantValue * 3;

        }
        tripleImportantValue();
        alert(this.importantValue);
    }
};

myWonderfulObject.displayTripledImportantValue(); //OK: it correctly alerts 6.


In the next wondrous episode the Constructor and the Apply patterns...