This. Method Is Not Function with setInterval [Duplicate]

I have this simple code:

var Modules = (function() {
    'use strict';

    return {
        
        TIMER: function (){
            var timer = null;
            
            return {
                time: 100,
                init: function() {
   
                    this.counter();
                    this.timer = window.setInterval(this.counter, 1000);
                },
                counter: function() {
                    this.time -= 1;

                    if (this.time <= 0) {
                        window.clearInterval(this.timer);
                        alert('Time expired');
                    }
                    console.log(this.time);
                    this.viewer();
                    
                },
                viewer: function() {
                    document.getElementById('timer').innerHTML = this.time;
                }
            }
        }
    };
}());

Modules.TIMER().init();
<div id="timer"></div>

And something is wrong because I got 2 errors:

this.viewer is not a function

and

NaN of this.time

What it wrong with my design pattern running over interval?

After extend TIMER to reset method:

reset: function() {
                    this.time = 100;
                }

and call it outside as: Modules.TIMER().reset(); ?

I got

this.time is not defined

.

Or inside init:

jQuery("body").on('keyup mouseup', function (e) {
                        this.reset();
                    });

I got error:

this.reset() is not s function.

1

2 Answers

Your issue is coming from this line:

this.timer = window.setInterval(this.counter, 1000);

When you are invoking the callback in the setInterval method, the this in the callback function no longer refers to your TIMER object, but the window.


Solution A: Use .bind(this) to bind lexical this to callback

You will need to bind the current context to the callback:

this.timer = window.setInterval(this.counter.bind(this), 1000);
var Modules = (function() {
    'use strict';

    return {
        
        TIMER: function (){
            var timer = null;
            
            return {
                time: 100,
                init: function() {
   
                    this.counter();
                    this.timer = window.setInterval(this.counter.bind(this), 1000);
                },
                counter: function() {
                    this.time -= 1;

                    if (this.time <= 0) {
                        window.clearInterval(this.timer);
                        alert('Time expired');
                    }
                    console.log(this.time);
                    this.viewer();
                    
                },
                viewer: function() {
                    document.getElementById('timer').innerHTML = this.time;
                }
            }
        }
    };
}());

Modules.TIMER().init();
<div id="timer"></div>

James H. Sterling

James H. Sterling

Environmental Science & Climate Journalist

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.