yash shukla
yash shukla

Reputation: 49

Confused with arrow functions javascript

This is the code i am using to increment intVariable value using window.setinterval.

var Arrow = (function () {
    function Arrow() {
        this.intVariable = 1;
        this.itemId = -1;
        this.interval = 25;
    }
    Arrow.prototype.activateTimer = function () {
        if (this.itemId === -1) {
            window.setInterval(this.showTimer(), this.interval);
        }
    };
    Arrow.prototype.showTimer = function () {
        this.intVariable += this.interval;
        console.log(this.intVariable);
    };
    return Arrow;
}());
var arrow = new Arrow();
arrow.activateTimer();

When I use below line the show timer function is called only once

window.setInterval(this.showTimer(), this.interval);

But when i change it to :

window.setInterval(() => this.showTimer(), this.interval);

It works perfectly.

Need some help why it worked using arrow function.

Upvotes: 1

Views: 95

Answers (3)

Ahmet Can Güven
Ahmet Can Güven

Reputation: 5462

You should provide function to interval, not the return of the function.

Whenever you write window.setInterval(this.showTimer(), this.interval); Actually you are doing this

var returnValue = (function () {
  this.intVariable += this.interval;
  console.log(this.intVariable); // You get your log for once
})() // -> null
window.setInterval(returnValue/*null*/, this.interval);

Then setInterval tries to call null after each this.interval and this won't give you an error on console.

But when you call it with arrow () => this.showTimer() this means:

var returnValue = function() {
  this.showTimer();
} // -> Function
window.setInterval(returnValue/*Function*/, this.interval);

You are providing a function to interval.


And also if you forget to bind your function to this scope you won't be able access your arrows scope. As a result you may see lots of NaNs

setInterval tries to call your registered function with global scope which is window. So when you write this in your function it will take this as window. So whenever you try to log this.intVariable it tries to log window.intVariable which is not defined.

So we should bind our function to current objects scope. So that whenever you use this, your scope will be binded to your current object (Arrow). And you get get your current arrows intVariable.

But whenever you write () => you create anonymous function like above and you already connect its scope into the object. So you won't need additional binding.

Here is your solution

    var Arrow = (function () {
        function Arrow() {
            this.intVariable = 1;
            this.itemId = -1;
            this.interval = 25;
        }
        Arrow.prototype.showTimer = function () {
            this.intVariable += this.interval;
            console.log(this.intVariable);
        };
        Arrow.prototype.activateTimer = function () {
            if (this.itemId === -1) {
                window.setInterval(this.showTimer.bind(this), this.interval);
            }
        };
        return Arrow;

}());
var arrow = new Arrow();
arrow.activateTimer();

Here is a fiddle

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386560

You could use directly the function reference (without using parenthesis)

window.setInterval(this.showTimer, this.interval);

By using a function call,

window.setInterval(this.showTimer(), this.interval);
//                               ^^

you insert the result of the function call and not the function itself.

When you use

window.setInterval(() => this.showTimer(), this.interval);

you insert a function without actually calling it.

Upvotes: 2

Tripurari Shankar
Tripurari Shankar

Reputation: 3548

window.setInterval(() => this.showTimer(), this.interval);

is like

window.setInterval(function() {this.showTimer()}, this.interval);

window.setInterval(this.showTimer(), this.interval); not work because you need to only pass the this.showTimer but you are calling it on the fly

Upvotes: 0

Related Questions