'Why doesn't typescript use the 'self' trick?

I wrote the following TypeScript code:

class Person {
    constructor(public firstname: string, public lastname:string){
}

public die(){
    this.lastname += " RIP";
}

And this compiles to:

var Person = (function() {
    function Person(firstname, lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
    }

    Person.prototype.die = function () {
        this.lastname += " RIP";
    };
    return Person;
})();

Which of course is a valid way, but it will not work as expected in the following case:

function run(delegate){
    delegate();
}

var person = new Person("guy", "dude");
run(person.die);
alert(person.lastname);
alert(lastname);

The expected alerts here would be "dude RIP", and then "undefined". However, the actual result would be "dude" and "undefined RIP". This is because the this parameter works strangely in JS.

A common solution to that is to use a self variable by closure, and to abandon the prototype mechanism, i.e.

var Person = (function() {
    function Person(firstname, lastname) {
        var self = this;
        self.firstname = firstname;
        self.lastname = lastname;
        self.die = function() {
            self.lastname += " RIP";
        }
    }
    return Person;
})();

Which would work as expected. What is advantage of that specific way to compile code? Did typescript decide to leave that piece of unintuitive code?



Solution 1:[1]

You need to change the structure of your code slightly to get it to use the _this = this pattern:

class Person {
    constructor(public firstName: String, public lastName: String) {
    }

    die = () => {
        this.lastName += "dead"
    }
}

Becomes:

var Person = (function () {
function Person(firstName, lastName) {
    var _this = this;
    this.firstName = firstName;
    this.lastName = lastName;
    this.die = function () {
        _this.lastName += "dead";
    };
}
return Person;
})();

The key part is that you need to place the die function on the object not the prototype, which forces it to use _this = this.

Solution 2:[2]

You should use the arrow function syntax when you want to capture this. I think it would be better to use this at the sight of delegate creation instead of class creation.

The only change needed would be:

run(()=>person.die());

This allows you to capture this for any function regardless of how it was defined.

Solution 3:[3]

Because that is how classes in JS works. Typescript devs decided they didn't want to change any pre existing features of the lang.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 xmojmr
Solution 2 Titian Cernicova-Dragomir
Solution 3 peter duffy