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: