When this does not work, use that

There is an issue in "this", the JavaScript keyword identifying the current object.
It works fine in an object member functions (AKA methods) but not in their inner functions. An easy way to bypass the problem requires us to create a member variable, that is often called "that" (or "self", but it is usually considered a weaker option).

Does it remember you an Abbott & Costello skit, "who's on first?", or it is just me? Anyway, an example should help clarifying the matter.

Say that we want to have an object, named calculator, keeping an internal status and providing a couple of methods, opA() and opB(), to perform some obscure calculations. The first operation is not too complicated, but opB() requires some messy stuff to be done, and we think that it would be a good idea to organize it defining an inner function that, among the other things, calls a free function.

It should be all not too complex to do, still we have to deal with the above mentioned issue.
var elaborate = (function(x) { // 1
    var cache = 0;

    return function(x) {
        cache += x;
        return cache;
    }
}());

var calculator = {
    status: 0,
    opA: function(x) { // 2
        this.status += x;
    },
    opB: function() { // 3
        var that = this; // 4
        var somethingComplicated = function() {
//            this.status += elaborate(this.status); // 5
            that.status += elaborate(that.status); // 6
        };
        
        somethingComplicated(); // 7
    }

    calculator.opA(3);
    calculator.opA(4);
    calculator.opB();
    console.log(calculator.status);
};
1. I defined elaborate() as a closure, so that it could keep its own status. See details in a previous post, static variable by closure.
2. This first method is trivial. It gets a parameter in input (assumed to be a numeric value), and adds it to the object property (status). To access the object property the keyword "this" is used. Not an issue here, for the object methods, the bind between "this" and the object itself is correctly done by JavaScript.
3. More complications here. In opB() we define a function, somethingComplicated(), that calls elaborate(), the closure defined in (1). The issue is that we can't use "this" in the body of somethingComplicated(), because "this", at that point, refers to the global scope or is undefined (if we "use strict" JavaScript, as we should).
4. "this" don't work as we would like in inner functions, but we can patch this behavior defining a local variable in the function, often called "that", that stores the value of "this" so to do as a bridge to the inner function.
5. As said above, this line doesn't work. "this" is undefined ("use strict") or points to the global scope. Hardly what you usually need.
6. This line saves the day. We use "that" to get access of the unavailable "this".
7. So we can happily call our somethingComplicated() inner method.

No comments:

Post a Comment