Reputation: 67
Just trying to learn Angular 2+ (8 specifically) and for the life of me, I can't understand why a class variable is 'undefined' inside a class function, but accessible if I write the function with ES6 style.
I tried setting in constructor instead, but that doesn't make sense.
export class GameControlComponent implements OnInit {
myVar;
counter = 0;
constructor() {} ngOnInit() {}
handleClickStart() {
this.myVar = setInterval(this.myFunc, 1500);
}
myFunc() {
this.counter++;
console.log(this.counter);
}
}
Once 'handleClickStart' is called, this outputs NaN every 1.5 seconds. Why???? I would have expected 1 2 3....
Implementing handleClickStart this way gives me the desired results:
handleClickStart() {
this.myVar = setInterval(() => {
console.log(this.counter + 1);
this.counter++;
}, 1500);
}
But still can't figure out why it didn't work out the first way.
Upvotes: 3
Views: 4040
Reputation: 1898
This behaviour has to do with scopes, arrow functions,this
and how Javascript functions/objects work.
Functions in JavaScript run in a specific context and using this
accesses the current context. this.counter
in the sample code is not available/defined inside setInterval()
function, so we get undefined
.
Now, in Arrow functions, things are special/different. Arrow Functions always lexically bind the context (Lexical Scoping means that it uses this
from the code that contains the Arrow Function.) and therefore this
will refer to the originating context, ie the class.
A simpler example might make it more clear.
const obj = {
myVar: 'foo',
myFunc: function() {
console.log('Actual Variable value: ',this.myVar)
setTimeout(() => {
console.log('Set timeout using Arrow function: ',this.myVar)
}, 1000);
setTimeout(function () {
console.log('Set timeout using Normal function: ',this.myVar)
}, 1000);
}
}
obj.myFunc();
Output
Actual Variable value: foo
Set timeout using Arrow function: foo
Set timeout using Normal function: undefined
Read more
Upvotes: 6