THIS

 

Like I have mentioned in the previous posts, the code I am converting is several years old. One of the things it does is some browser detection on page load (a technique that is generally no longer in favor).  Changing the functionality or refactoring the code prior to TypeScript conversion however was not a goal.  During the conversion of this detector  object (which was not prototype or closure style) I started with something structured something like this:


var MyNamespace = MyNamespace || {};

MyNamespace.detector = {

    name: "4",
    init: function () {
        this.name = this.name + "test";
        this.other();
    }, 
    other: function () {
        this.name = "test3";
    },


    dostuff: function (x) {
        alert(this.name + ' ' + x);
    }
}


MyNamespace.detector.init();

MyNamespace.detector.dostuff('z');

And converted it to this TypeScript :


module MyNamespace
{
    export module detector
    {
        export var name : string = "4";

        export function init():void
        {
            this.name = this.name + "test";
            other();
        }

        function other():void
        {
            this.name = "test3";
        }

        export function dostuff(x:string):void
        {
            alert(this.name + ' ' + x);
        } 
    }

}

MyNamespace.detector.init();

MyNamespace.detector.dostuff('z');

The way the “other” function was handled led to issues.  I had essentially tried to make it private by not exporting it as it is not something external code would use directly. A quick glance at the code above might give one the impression that the alert would say ‘test3 z’ but in reality it shows ‘4test z’.  That is because the “this” in the function “other” is actually a different “this” than in “dostuff” or “init”.  The transpiled TypeScript code below makes it clearer why.  “this” in the function “other” is the function, while for “init” and “dostuff” it is the object “detector”.  The other catch with this situation is that TypeScript will happily let you assign to “this” in a standalone function, even if you set the “allow implicit any types” compiler directive off.  Secondly, the “export var name” is actually not required because of the way “this” is handled.  TypeScript will compile the file with no errors without that declaration.

My own advice from this “this” experience would be to wary of function exports from modules that use “this” and to check them carefully.  In my experience so far, using “this” in TypeScript classes has more protections.

var MyNamespace;
(function (MyNamespace) {
    (function (detector) {
        detector.name = "4";
        function init() {
            this.name = this.name + "test";
            other();
        }
        detector.init = init;

        function other() {
            this.name = "test3";
        }

        function dostuff(x) {
            alert(this.name + ' ' + x);
        }
        detector.dostuff = dostuff;
    })(MyNamespace.detector || (MyNamespace.detector = {}));
    var detector = MyNamespace.detector;
})(MyNamespace || (MyNamespace = {}));

MyNamespace.detector.init();

MyNamespace.detector.dostuff('z');

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

OR

LOGIN OR REGISTER

Registered users with one approved comment can comment without moderation