1

Written in typescript, I have this:

export class EventDiscussionPage {
    messages: any = []
    private _channel: any;
    initChat() {
      this._channel.on('messageAdded', function(message) {
        this.messages.push(message);
      }
    }
}

When a message is added, I get cannot read property 'push' of undefined. I guess I'm having a scope issue - how do I add the message to this.messages?

Chris Rockwell
  • 1,688
  • 2
  • 21
  • 36
  • 1
    Try an arrow function instead: `this._channel.on('messageAdded', (message) => {` – Andy Dec 11 '17 at 21:10
  • Well dang that was quick - and it worked :). `this._channel.on('messageAdded', message => this.messages.push(message))`. I guess i need to dive deeper into scope and why arrow functions are different. Please add as an answer so I can accept - thanks! – Chris Rockwell Dec 11 '17 at 21:13
  • 1
    @ChrisRockwell [This book](https://github.com/getify/You-Dont-Know-JS/tree/master/this%20%26%20object%20prototypes) from Kyle Simpson may help – mhodges Dec 11 '17 at 21:18
  • 1
    @ChrisRockwell, the short answer is that arrow functions don't have a `this` of their own so look for the `this` in the outer lexical environment. – Andy Dec 11 '17 at 21:24

2 Answers2

3

Instead of using a function close over, where the function closure causes the this to be reassigned, you can use an ES6 lambda.

You get something similar to this._channel.on('messageAdded', (message) => this.messages.push(message));

More information about the this scope in Javascript can be found here How to access the correct `this` inside a callback?

Rogier Slag
  • 526
  • 3
  • 7
3

You have a scoping issue. Use context:

export class EventDiscussionPage {
    messages: any = []
    private _channel: any;
    initChat() {
      var ctx = this;
      this._channel.on('messageAdded', function(message) {
        ctx.messages.push(message);
      }
    }
}

the this you are referring to is the "_channel", you basically need to carry a reference from the parent to correctly call it.

You can also use the arrow function syntax to avoid this (as it will carry over the context of the parent):

export class EventDiscussionPage {
    messages: any = []
    private _channel: any;
    initChat() {
      this._channel.on('messageAdded',(message) => {
        this.messages.push(message);
      }
    }
}
asosnovsky
  • 2,158
  • 3
  • 24
  • 41