0

I'm trying to get my head around various javascript concepts and one thing I'm failing to understand is why this works:

var counterObject = {
    counter: 0,
    start: function () {
        this.i++;
        console.log(this.i);
    }
};
setInterval(() => counterObject.start(), 1000);

Yet, when I try and make this a recursive function, I cannot get access to the counter variable:

var counterObject = {
    counter: 0,
    start: function () {
      setInterval(function() {
        this.i++;
        console.log(this.i);
        this.start;
      }, 1000)
    }
};
counterObject.start();

This will always return NaN, and i can't seem to understand why? Just learning so go easy on my guys ;)

user3024827
  • 1,228
  • 4
  • 18
  • 36
  • I'll let someone else answer for sure, but I believe this is a scoping issue. In the first example `this` refers to the context of the object `counterObject` while in the second example `this` refers to the context of the anonymous function of the `setInterval` callback... – War10ck Nov 01 '18 at 20:07
  • `i` is never declared or initialized. What happens when you add `1` to `undefined`? You get `NaN`. –  Nov 01 '18 at 20:07
  • Have you tried using an arrow function for the setInterval callback in the second block? – Taplar Nov 01 '18 at 20:07
  • @Amy yes I have an the same result – user3024827 Nov 01 '18 at 20:11
  • https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#The_this_problem – epascarello Nov 01 '18 at 20:16
  • Pass `this` as the argument to the interval callback, and use it that way. – evolutionxbox Nov 01 '18 at 20:16

1 Answers1

0

You have several issues in your code. I will try to explain most of them in the comments of the following code

var counterObject = {
    counter : 0,
    start : function() {

        const that = this;

        setInterval( function() {

            // This function has a different scope so `this` is not your `counterObject`
            // anymore. In order to use it you need to make a reference to it

            /*
            this.i++;
            console.log( this.i );
            this.start;
            */

            // i? You probably meant counter, btw
            that.counter++;
            console.log( that.counter );

            // Invoking a function always need parenthesis, so you should add those
            // to make the recursive call
            that.start();

        }, 1000 );
    }
};
counterObject.start();
drinchev
  • 19,201
  • 4
  • 67
  • 93
  • 1
    Given that this logic involves an interval, the repeated call to `that.start()` seems like a logic flaw. Not directed at you, given that it was in the OP question, but still. – Taplar Nov 01 '18 at 20:13
  • 1
    @Taplar I agree. Removing that line or changing `setInterval()` to `setTimeout()` would seem to be more logical. – War10ck Nov 01 '18 at 20:15
  • Okay thanks - clears things up and the code now works - set Timeout was initially my first approach – user3024827 Nov 01 '18 at 20:16
  • Agree with everyone. However having to explain more on that, seemed out of the scope of this question. – drinchev Nov 01 '18 at 20:16