scope - JavaScript - setInterval with passed function does not recognize global variables - Stack Overflow

I was stuck in some weird problem and then the problem got a challenge to understand why Angular behave

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?

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?

Share Improve this question edited Aug 22, 2018 at 20:19 Bharata 14.2k6 gold badges43 silver badges53 bronze badges asked Jan 14, 2018 at 22:15 Moshe BinieliMoshe Binieli 4614 silver badges22 bronze badges 1
  • 1 setInterval(() => this.foo(), ...) or setInterval(this.foo.bind(this), ...) or ... This is nothing to do with Angular/TS/ES6, see any JS this scoping question. – jonrsharpe Commented Jan 14, 2018 at 22:45
Add a ment  | 

2 Answers 2

Reset to default 6

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 particular this value.

A mon 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.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745000251a4605449.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信