I am creating a library and one of the patterns I need to implement is event handling. I am writing in TypeScript, but this issue is basically in Javascript. Consider this code:
class MessageRelayer {
    private readonly listeners: Array<(args: string) => void> = [];
    public addListener(listener: (args: string) => void): void {
        this.listeners.push(listener);
    }
    public relayMessage(msg: string): void {
        for (const listener of this.listeners) listener(msg);
    }
}
class TestClass {
    private el: string;
    constructor(private readonly relay: MessageRelayer) {
        this.el = "example";
    }
    public initialize(): void {
        this.relay.addListener(this.onRelayed);
    }
    private onRelayed(e: string): void {
        console.log("EL is:", this.el);
    }
}
const relay = new MessageRelayer();
const stuff = new TestClass(relay);
stuff.initialize();
relay.relayMessage("Hello world"); // Error here
When running this code, it gives me error in onRelayed:
Cannot read property 'el' of undefined
If initialize is written as:
public initialize(): void {
    this.relay.addListener((e: string) => { console.log("EL is:", this.el); });
}
It works.
Questions
I understand this is about the famous this binding issue. But what's happening is not something I can explain here. What I think it should happen is:
- When calling initialize(), functionTestClass.onRelayedis passed toMessageRelayer. It means that in that moment,thisforTestClass.onRelayedwill be bound toMessageRelayer.
- As soon as relayMessageis invoked,MessageRelayerwill get the saved instance ofTestClass.onRelayedwhosethisis now pointing toMessageRelayer, and executed it.
- I should get an error that thisdoes not containel.
Instead I find out that this is actually undefined. What is happening here?
