I was stuck in some weird problem and then the problem got a challenge to understand why Angular behaves like this, there was no much luck searching at Google for the problem, so I am here.
I wanted to test setInterval() function and counter some variable, not something too hard, and I got stuck in problem that I couldn't find solution for or explaination.
This is my code I am using and it works fine:
public counter: number = 1;
myFunction() {
setInterval(() => {
console.log(this.counter);
this.counter++;
}, 1000);
}
Output: 1, 2, 3, 4, 5...
This code works fine, but when I am taking the function to be like this, I get undefined as output and then Nan, Nan, Nan.
public counter: number = 1;
foo() {
console.log(this.counter);
this.counter++;
}
myFunction() {
setInterval(this.foo, 1000);
}
* myFunction is the starting function *
Output: undefined, Nan, Nan, Nan...
I guess there is some problem with variables access that foo() cannot access the global variables, but how is that happening? and how can I fix this problem?
here's a code that acts as you discribed
class A{
public counter: number = 1;
foo() {
alert(this.counter);
this.counter++;
}
myFunction() {
setInterval(this.foo, 1000);
}
}
const a = new A();
a.myFunction(); // output andefined, Nan, Nan ...
now the code using bind : JSFiddle
class A{
public counter: number = 1;
foo() {
alert(this.counter);
this.counter++;
}
myFunction() {
setInterval(this.foo.bind(this), 1000);
}
}
const a = new A();
a.myFunction(); // output 1, 2, 3, 4 ...
this is a very tricky subject so
first check this question How to access the correct 'this' inside a callback?
and couple of insanely good answer about the subject here and here .
now the bind method - Function.prototype.bind() :
(from the docs)
The
bind()method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
and loved this expletetion (took from the Examples part in the docs) :
The simplest use of
bind()is to make a function that, no matter how it is called, is called with a particularthisvalue.A common mistake for new JavaScript programmers is to extract a method from an object, then to later call that function and expect it to use the original object as its
this(e.g. by using that method in callback-based code). Without special care, however, the original object is usually lost.Creating a bound function from the function, using the original object, neatly solves this problem
In the first example you are passing a function declared in es6 shorthand (link here), therefore "this" will be bound to the current scope.
In the second example you are passing a reference to a function and because setTimeout executes the function with this pointing to the global object, "this" equals the window object and therefore the properties are undefined.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With