JavaScript - 带有传递函数的setInterval无法识别全局变量

时间:2018-01-14 22:15:38

标签: javascript scope callback function-pointers setinterval

我遇到了一些奇怪的问题,然后问题就明白了为什么Angular会像这样行事,没有多少运气在谷歌搜索问题,所以我在这里。< / p>

我想测试setInterval()函数并计算一些变量,而不是太难,我陷入了无法找到解决方案或解释的问题。

这是我正在使用的代码,它运行正常:

public counter: number = 1;

  myFunction() {
    setInterval(() => {
      console.log(this.counter);
      this.counter++;
    }, 1000);
  }

Output: 1, 2, 3, 4, 5...

这段代码工作正常,但是当我把这个函数变成这样的时候,我得到了未定义的输出,然后是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...

我猜变量访问存在一些问题,foo()无法访问全局变量,但是这是怎么回事?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

这里的代码就像你描述的一样

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

现在代码使用绑定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 ...

这是一个非常棘手的主题,所以

首先检查此问题How to access the correct 'this' inside a callback?

关于主题herehere的几个非常好的答案。

现在绑定方法 - Function.prototype.bind()

(来自文档)

  

bind()方法创建一个新函数,在调用时,将其this关键字设置为提供的值,并在调用新函数时提供任何前面提供的给定参数序列。

并喜欢这个expletetion(摘自docs中的示例部分):

  

bind()的最简单用法是创建一个函数,无论它如何调用,都使用特定的this值调用。

     

新JavaScript程序员的一个常见错误是从对象中提取方法,然后调用该函数并期望它将原始对象用作this(例如,在回调中使用该方法)码)。   但是,如果没有特别小心,原始对象通常会丢失。

     

使用原始对象从函数创建绑定函数,巧妙地解决了这个问题

答案 1 :(得分:1)

在第一个示例中,您传递的是以es6简写(链接here)声明的函数,因此"this"将绑定到当前范围。

在第二个示例中,您正在传递对函数的引用,并且因为setTimeout执行函数,并指向全局对象,"this"等于窗口对象,因此属性未定义。 / p>