0

I seem to be having scoping issues on a typescript class in which I'm trying to see if I can get rid of anonymous functions. I've been going between using the arrow method and not. So for example -

//blah is globally available
export class Foo {
    addSomeListeners = () => {
        blah.addListener( this.eventHandler );
    }
    eventHandler( someProperties ){
        blah.get( somePropreties, this.anotherCallback );
    } 

    anotherCallback = ( data ) => {
      //do something with the data
    }

}

So elsewhere in the code I create an instance of Foo and I call the addSomeListeners method. This works fine. Later an event is fired and the eventHandler method gets called - all still good.

Now inside the eventHandler method it does some stuff and calls a get method that needs a callback. Its at this point that the 'this' property is null - so it has no idea what 'anotherCallback' is.

I'm guessing its a simple scoping issues, but I can seem to figure it right now. I'd like to be able to remove all anonymous functions, so rather than define the method in the blah.get( ...) signature I can call a method from within the Foo class to reuse.

EDIT - This question is not a duplicate as the duplicate doesn't deal with Typescript, it does mention ECMA6 arrow functions but doesn't solve the issue I am having. So yes very similar, but not similar enough IMO to be a duplicate.

So for example I have an instance of Foo (say foo) where I call foo.addSomeListeners(). Now in that method 'this' is foo - which is what I'd expect. Then a bit later the eventHandler method gets called due to the event - but inside that 'this' is null.

delp
  • 771
  • 11
  • 20
  • It's not a problem of scope but a problem with how `this` works. Are you really using `anotherCallback = ( data ) => {}` in your code? Is that a Typescript feature? I know that it is an ECMAScript proposal and if you really use that in your code, you should actually see a problem. So either your code is different or you have a different problem (in which case you need to provide a better example). – Felix Kling Oct 04 '16 at 17:07
  • I went through more than a few different connotations of using the arrow function and the normal way - and so far I've been unable to get hold of 'this' in the 2nd callback. Listing each variation would make the Q unreadable so I thought I'd try to keep it as short but accurate as possible. All of my attempts are valid Typescript code (ECMA6+), if they were not then it wouldn't compile. – delp Oct 04 '16 at 20:46
  • Sorry, I got confused. The duplicate explains what the issue is and provides multiple ways to solve this problem. But you can also do change `eventHandler` to a class property (`eventHandler = ( someProperties ) => { blah.get( somePropreties, this.anotherCallback ); }`). – Felix Kling Oct 04 '16 at 21:00
  • It exactly a duplicate. The difference is only that there is one more solution for Typescript, which I mentioned in the comment. E.g. a solution from the duplicate would be to use `.bind`: `blah.addListener( this.eventHandler.bind(this));` – Felix Kling Oct 04 '16 at 21:13
  • I shall try that. I also tried passing in a reference to the eventHandler method from the foo instance, just to see if that did anything. so foo.addSomeListeners( foo.eventHandler ) and referenced that - but didn't do anything. – delp Oct 04 '16 at 21:14
  • It seems you first need to develop a better understand of how `this` works. Have a look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this or https://github.com/getify/You-Dont-Know-JS/tree/master/this%20%26%20object%20prototypes . But anyway, you have slots of possible solutions available now. – Felix Kling Oct 04 '16 at 21:16
  • I'm may be mistaken - but I thought the whole point of Typescript and arrow functions was to get away from needing to add things like .bind. If I have to then I have to, but I'd rather not. – delp Oct 04 '16 at 21:17
  • Arrow functions help in many cases but not in all. As I said, you don't have to `.bind(this)`, you can just defined `eventHandler` as an arrow function as well (see one of my previous comments). Basically the issue is that you defined all the methods arrow functions, except `eventHandler`. – Felix Kling Oct 04 '16 at 21:18
  • Thanks, I have tried that (thought I had previously, but wasn't 100%) so I've rechecked - all functions are arrow functions and yet inside the eventHandler 'this' is null. – delp Oct 04 '16 at 21:26
  • It works fine if I try it here: https://jsfiddle.net/8c6zeu6s/ . You can also take a look at the compiled code on http://www.typescriptlang.org/play/index.html , which makes it very obvious that the value can't be `null`. – Felix Kling Oct 04 '16 at 21:30
  • I can that works and I'm trying to see if I can amend it to be closer to what I have, but the flow is the same so it should be the same result. Cheers – delp Oct 04 '16 at 21:42
  • Finally I have a solution! As Felix showed in the demo which is almost identical it should never have been null. The only way this could be null is if there was some sort of conflict in instances. The global blah was actually chrome.tabs (which didn't seem important at the time of the Q), so the code extension must be duplicated in every tab (unsure of how exactly each tab holds its instances) - so by making the methods static I got around the issue. There may be a cleaner way, but at the moment it works. – delp Oct 04 '16 at 22:02

0 Answers0