TDaver
TDaver

Reputation: 7264

TypeScript: so how exactly is "this" scoped?

I have this piece of Typescript code:

constructor($triggerHref: JQuery) {
        // stuff...
        var _this = this;
        $(document).on("click",$triggerHref.selector,e=>{
            e.preventDefault();
            var target = $(e.srcElement).attr("data-pcc-sort-trigger");
            if (target == _this.active)
                _this.load(target, !_this.isDescending);
            else _this.load(target, false);
        });

    }

If I remove the var _this = this; line and just use this inside the event handler, the generated js code looks reasonably the same (it generates the _this anyway), yet for some reason this.active and this.load() are undefined.

My understanding of TS's scoping was that ()=>{} methods keep the this from their parents, and only function(){} methods work like usual JS methods.

So why is this one not working for me?

Upvotes: 4

Views: 711

Answers (2)

vinczemarton
vinczemarton

Reputation: 8156

As you have already noticed, lambda functions capture this at the time the lambda function is defined. This can lead to wierd results (also there are a few bugs around var _this = this), although most of these seems to be fixed.

The whole language construct seems to be for the purpose of cheating JavaScript scoping (this is the object that the function is called on).

As for the weirdness you explained (this.active and _this.active behaving differently), there is no explanation inside the scope of the question.

The generated JavaScript (as you have stated) should be (nearly) the same. Well apart from writing var _this = this; leading to _this defined more than once in the same scope and breaking javascript validity. This is a problem around TypeScript lambdas. Never define _this in TS as it is reserved for some purposes (and not checked if it's free).

And there is no magic in TypeScript. What gets executed is the JavaScript it generates. Check if something overwrites _this in the same scope (which would be easy to spot since the scope of var _this is the scope of the constructor function, also var hides the variables with the same name coming from an outer scope, so it should be inside the constructor).

I avoid using lambda expressions in TypeScript for now. Using simple anonym functions instead, does not require you to restructure any of your code. Saving this to an other variable can be considered ugly yes, but you can work around it by using $.proxy() for example. This way you can even write a regex replace to change your lambdas to $.proxy(). For now.

So all in all I would need to debug the generated JS to spot the error since your code should be syntactically fine. It seems to me that the TypeScript compiler needs some rethinking around this (I hope some TS enthusiasts will differ and teach me how it is properly done, as I'm not agains TS, on the contrary).

I'm pretty sure @RyanCavanaugh would be able to prepare a better answer.

Upvotes: 1

Guffa
Guffa

Reputation: 700152

The lambda expression generates a function expression, so the same rules for scope applies to a lambda expression as a function expression.

Example:

var x = e => {};

genrates this Javascript code:

var x = function (e) {
};

Upvotes: 0

Related Questions