1

Given the following class:

class TimerFunk {
    constructor(someObject){
        this.a = 1
        this.someObject = someObject
    }
    funk(){
        console.log(this.a)
        if(this.a > 2){
            return
        }
        this.a++
        this.someObject.execCallback(this.funk)
    }
}

When the following commands are executed:

t = new TimerFunk({execCallback:function(callback){callback()}})
t.funk()

it is intended that the property TimerFunk.a is logged to the console until this.a>2. However instead the loop only executes once:

VM2097:9 1
VM2097:9 Uncaught TypeError: Cannot read property 'a' of undefined
    at funk (<anonymous>:9:25)
    at Object.execCallback (<anonymous>:5:13)
    at TimerFunk.funk (<anonymous>:13:25)
    at <anonymous>:1:3

From debugging I have figured out that this is because on the first loop this represents the object t however, on the 2nd loop this represents someObject.

Is there any way I can fix this and allow me to access class properties from within the executed callback?

Sancarn
  • 2,575
  • 20
  • 45

1 Answers1

2

Your callback is called without the TimerFunk instance t as the this object:

function(callback){callback()}}

A solution is to bind the this object of the callback to the TimerFunk instance:

funk() {
  ...
  this.someObject.execCallback(this.funk.bind(this));
}

Alternatively, you can explicitly pass t as the this object via callback.call(t):

t = new TimerFunk({execCallback:function(callback){callback.call(t)}});
le_m
  • 19,302
  • 9
  • 64
  • 74
  • Intuitively I would assume that this.funk.bind(this) wouldn't return funk. Very glad this functionality exists though as I wanted to avoid passing t as an argument if possible! Thanks! – Sancarn Jun 09 '17 at 01:06