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



我陷入了一些奇怪的问题,然后这个问题很难理解为什么 Angular 会表现得像这样,在谷歌搜索这个问题没有太多运气,所以我在这里。

我想测试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() 无法访问全局变量,但这是怎么回事? 我该如何解决这个问题?

这是一个按照你描述的代码

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

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

首先检查这个问题 如何在回调中访问正确的"this"?

以及关于这里和这里的几个关于这个主题的疯狂的好答案.


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

(来自文档)

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

并喜欢这个解释(取自文档中的示例部分):

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

对于新的 JavaScript 程序员来说,一个常见的错误是从对象中提取方法,然后调用该函数并期望它使用原始对象作为其this(例如,在基于回调的代码中使用该方法)。 然而,如果没有特别的照顾,原始物体通常会丢失。

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

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

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