Inside setInterval, "this" does not point to the function that called it

Asked

Viewed 63 times

2

The context in which this Arrow was created was directly in the method setInterval, however the this points to the idade inside the object Pessoa, why? The this in Arrow is based on the context in which it was written, in which case the context of a function called setInterval, right?

function Pessoa(){
    this.idade = 0

    setInterval(() => {
        this.idade++
        console.log(this.idade)
    },1000)
}

new Pessoa();

The second case is why you have to use bind in the same code without Arrow? Since it is a function, why not point to the object that is creating it?

console.log(this === window);

function Pessoa(){
    this.idade = 0;

    setInterval(function(){
        this.idade++
        console.log(this.idade)
    }.bind(this),1000);
}

new Pessoa();

1 answer

1

This is explained in documentation:

Code executed by setInterval() runs in a Separate Execution context than the Function from which it was called. As a consequence, the this keyword for the called Function is set to the window (or global) Object, it is not the same as the this value for the Function that called setTimeout.

In free translation:

The code executed by setInterval runs in a separate context from the function where it was called. Consequently, the this call function is set to the object window (or global), and is not the same this of the function that called setTimeout.

We can see this behavior changing your example a little:

var x = 0, id = 0;
function Pessoa(){
    this.idade = 0;

    id = setInterval(function() {
        this.idade++;
        console.log(this == window, this.idade); // true NaN
        // só pra não ficar executando eternamente
        if (x++ >= 2) clearInterval(id);
    }, 1000);
}

new Pessoa();

Spinning in a browser, the this will equal window, as stated in the documentation. And how window.idade was not defined (because on the line this.idade = 0, the this refers to the Pessoa), then within the function the value of this.idade is undefined, since he’s trying to catch window.idade.


Already using Arrow Function, the this is not amended in this way, and refers to the Pessoa:

var x = 0, id = 0;
function Pessoa(){
    this.idade = 0;

    id = setInterval(() => {
        this.idade++;
        console.log(this == window, this, this.idade); // false { "idade": valor } valor da idade 
        // só pra não ficar executando eternamente
        if (x++ >= 2) clearInterval(id);
    }, 1000);
}

new Pessoa();


And using bind also works, because the return of bind is a function equal to the original, but with the this set to the given value:

var x = 0, id = 0;
function Pessoa(){
    this.idade = 0;

    id = setInterval(function() {
        this.idade++;
        console.log(this == window, this, this.idade); // false { "idade": valor } valor da idade 
        // só pra não ficar executando eternamente
        if (x++ >= 2) clearInterval(id);
    }.bind(this), 1000);
}

new Pessoa();

In the case, .bind(this) is out of anonymous function, so at that point the this refers to Pessoa. That is, the bind returned a function equal to the anonymous function, but with the this set to the Pessoa.


What confuses in the above cases is that every moment the this can represent a different thing. It’s really confusing:

Browser other questions tagged

You are not signed in. Login or sign up in order to post.