简体   繁体   English

为什么以函数声明为参数的setInterval()与匿名函数的工作原理不同?

[英]Why setInterval() with a declaration of a function as an argument works differently than with anonymous function?

I don't understand why using function name in setInterval is not working correctly but passing annonymous function is working just right. 我不明白为什么在setInterval中使用函数名称不能正常工作,但传递匿名函数却可以正常工作。

not working example (it's console logging NaN and before calling first time this.counter++ it's returning undefined as it couldn't find the variable?) 不起作用的示例(它是控制台记录NaN的控制台,并且在首次调用this.counter ++之前,由于找不到变量,它返回的是undefined?)

export class MyClassName {
 counter = 0;

 startInterval(){
   setInterval(this.myFunc , 1000)
 }

 myFunc(){
   this.counter++;
   console.log(this.counter)
 }
}

but with startInterval changed like below it's working correctly 但是随着startInterval像下面这样更改,它可以正常工作

startInterval(){
  setInterval(() => this.myFunc() , 1000)
}

and in html we have 在html中,

<button (click)="startInterval()">Start</button>

In the first example, you pass in a function reference without running it. 在第一个示例中,您传递了一个函数引用而不运行它。 When it runs, it runs in the global context where this is undefined, or this refers to the Window object. 当它运行时,它运行在全球范围内,其中this是不明确的,或者this指的是Window对象。 You can verify that it does in fact refer to the Window object by logging the value of this.constructor.name : 您可以通过记录this.constructor.name的值来验证它是否确实引用了Window对象:

 class MyClassName { counter = 0; // You are passing in a function name but not running it yet. // It will be run in a global context by setInterval. startInterval(){ setInterval(this.myFunc, 1000) } myFunc(){ // When run in global context, this no longer refers to our instance. console.log(this.constructor.name); this.counter++; console.log(this.counter) } } const mc = new MyClassName(); mc.startInterval(); 

In the second example, arrow functions use the this of where they are declared, not where they are run. 在第二个示例中,箭头函数在声明它们的位置而不是在运行它们的位置使用this So the this of the class is captured below, even though the arrow function will run in the global context. 因此,即使arrow函数将在全局上下文中运行,该类的this仍在下面捕获。

 class MyClassName { counter = 0; // Arrow functions use the `this` of where they are declared, not where they are run. // So the `this` of the class is captured below, even though the arrow function // will run in the global context. startInterval(){ setInterval(() => this.myFunc(), 1000); } myFunc(){ console.log(this.constructor.name); this.counter++; console.log(this.counter) } } const mc = new MyClassName(); mc.startInterval(); 

You can find a pretty good summary of exactly how this works specifically with setInterval in the MDN docs for arrow functions . 您可以在MDN文档中的箭头功能中找到一个很好的摘要,特别是它与setInterval的配合方式。

The discrepancy is with the this keyword. 关键字之间存在差异。 In javascript anonymous/arrow functions do not create this to reference the caller of the function. 在javascript中,匿名/箭头函数请勿创建函数来引用函数的调用者。 while a conventional function declared with function keyword will capture the caller of the function in this . 而使用function关键字声明的常规函数​​将在this中捕获函数的调用者。

Therefore, in your first example the startInterval() is called by the button element, which doesn't have a counter variable. 因此,在第一个示例中,startInterval()由没有计数器变量的button元素调用。 And in the second example the this keyword refers to the outer scope this which is the window object. 并且在第二示例中的这个关键字指外部范围也就是窗口对象。 I assume MyClassName gets created under the window object, therefore the counter exists. 我假设MyClassName在窗口对象下创建,因此该计数器存在。

Further reading: https://www.codementor.io/dariogarciamoya/understanding-this-in-javascript-with-arrow-functions-gcpjwfyuc 进一步阅读: https : //www.codementor.io/dariogarciamoya/understanding-this-in-javascript-with-arrow-functions-gcpjwfyuc

That's because your this is calling to the function and therefore myFunc is not defined. 这是因为你this是调用的函数,因此myFunc没有定义。 You can learn about this context with a quick search. 您可以通过快速搜索来了解this上下文。 Some examples: 1 , 2 . 一些例子: 12


You can verify this by logging this.myFunc . 您可以通过记录this.myFunc进行验证。 The same will happen to this.counter if it ever gets called. 如果曾经被调用过, this.counter也会发生同样的情况。

 let counter = 0; const startInterval = () => { // undefined, and hence it does not exist. console.log(this.myFunc); setInterval(this.myFunc, 1000); }; startInterval(); const myFunc = () => { this.counter++; console.log(this.counter); }; 

You can simply fix your code by reordering the functions and removing this . 你可以简单地通过重新排序的功能,并删除修复您的代码this

 let counter = 0; const myFunc = () => { counter++; // Remove this from here as well. console.log(counter); }; const startInterval = () => { // Defined, and hence it works. setInterval(myFunc, 1000); }; startInterval(); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM