Madhu Ranjan
Madhu Ranjan

Reputation: 17944

How to update fat arrow function using prototype?

Is there a way in which we may update fat arrow function using prototype?

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet = () => {
        alert("Hello, " + this.greeting + " inside");
    }
}

Greeter.prototype.greet = () => {
    alert("Hello, " + this.greeting + " outside");
}

let greeter = new Greeter("world");
greeter.greet();
// It should alert Hello world outside
// But it is showing  Hello world inside

Am i understanding fat arrow syntax incorrectly, and it can not be updated like this, any reference would be helpful?

Here is the Link for Typescript Playground where I was trying

Thanks in Advance!!

Upvotes: 0

Views: 106

Answers (2)

Nitzan Tomer
Nitzan Tomer

Reputation: 164367

To understand what's going on better you should look at the compiled js code:

var _this = this;
var Greeter = (function () {
    function Greeter(message) {
        var _this = this;
        this.greet = function () {
            alert("Hello, " + _this.greeting + " inside");
        };
        this.greeting = message;
    }
    return Greeter;
}());
Greeter.prototype.greet = function () {
    alert("Hello, " + _this.greeting + " outside");
};

There is a greet function which is added to the prototype, but then when you create a new instance of Greeter this method is being overridden in the constructor.

It's usually better to have normal class methods:

class Greeter {
    // ...
    greet() {
        alert("Hello, " + this.greeting + " inside");
    }
}

Which then compiles into js with the alert already on the prototype:

var Greeter = (function () {
    function Greeter() {
    }
    Greeter.prototype.greet = function () {
        alert("Hello, " + this.greeting + " inside");
    };
    return Greeter;
}());

If you worry about losing the scope of this when executing greet (because you pass it as a callback or something similar) then it's easy to just:

setTimeout(greeter.greet.bind(greeter), 1000);

Or

setTimeout(() => { greeter.greet(); }, 1000);

Edit

If you want to do something like this:

class Greeter {
    greeting: string;
    message: string = "";
    constructor(message: string) {
        this.greeting = message;
    }
    greet(){
      return "Hello, " + this.greeting + " inside";
    }
}

let oldGreet = Greeter.prototype.greet;
Greeter.prototype.greet = function(){
   return oldGreet() + " appended outside";
}

It won't work as it will print:

"Hello, undefined inside appended outside"

And that's because the this isn't the instance of Greeter, it should be oldGreet.call(this):

Greeter.prototype.greet = function(){
   return oldGreet.call(this) + " appended outside";
}

(code in playground)

Upvotes: 2

Daniel Tran
Daniel Tran

Reputation: 6169

When you create a Greeter object. It sets:

this.greet = function () {
  alert("Hello, " + _this.greeting + "inside");
};

So it will override what you set in prototype. If you don't write the same greet() function, then it will call what you set in prototype.

Another thing to remember is that when you use arrow function:

Greeter.prototype.greet = () => {
  alert("Hello, " + this.greeting + " outside");
}

this. here is not the object itself, but it belongs to the outer context, that means you can't get this.greeting correctly.

Upvotes: 2

Related Questions