简体   繁体   English

setTimeout 中箭头函数与 es5 函数的范围

[英]Scope of arrow function vs es5 function in setTimeout

I am experimenting with this and arrow functions.我正在试验这个和箭头函数。 Ran into some trouble regarding the lexical scope of arrow function in setTimeout.关于 setTimeout 中箭头函数的词法范围遇到了一些麻烦。

The makeSound method returns this as the dog object. makeSound 方法将 this 作为狗对象返回。 Why does it not take the scope of the global object since the arrow function is inside the setTimeout method?既然箭头函数在 setTimeout 方法里面,为什么不取全局对象的作用域呢? Interestingly, the whatIsThis method returns the Timeout object and not the global object.有趣的是,whatIsThis 方法返回的是 Timeout 对象而不是全局对象。 I am confused on this as well.我对此也很困惑。

 const dog = { name: 'fluffy', type: 'dog', sound: 'woof!', makeSound: function() { setTimeout(() => { console.log("makeSound", this) }, 1000) }, whatIsThis: function() { setTimeout(function() { console.log("whatisthis", this) }, 1000) } } dog.makeSound() // returns dog obj dog.whatIsThis() // returns Timeout obj setTimeout(() => { console.log("global", this) }, 1000) // returns global obj

Why does it not take the scope of the global object since the arrow function is inside the setTimeout method? 为什么因为箭头函数位于setTimeout方法内部,所以它不采用全局对象的范围?

The callback is not "inside" the setTimeout function. 回调不在setTimeout函数内部。 It is passed as argument to the setTimeout function. 作为参数传递 setTimeout函数。

Consider the following, equivalent code: 考虑以下等效代码:

const dog = {
  name: 'fluffy',
  type: 'dog',
  sound: 'woof!',
  makeSound: function() {
    const cb = () => console.log("makeSound", this);
    setTimeout(cb, 1000)
  },
}

This code behaves exactly the same. 此代码的行为完全相同。 The only difference is that the callback function is assigned to variable first before being passed to setTimeout . 唯一的区别是,回调函数在传递给setTimeout之前先分配给变量。

This should demonstrate that the arrow function is not "inside" setTimeout , but rather inside makeSound . 这应该表明箭头功能不是在setTimeout内部,而是在makeSound内部。 Arrow functions resolve this lexically, just like any other variable. 箭头函数像其他变量一样,按词法解析this So we have to find out what the value of this inside makeSound is. 所以我们要找出什么价值this里面makeSound是。 And in order to find that out, we have to look at how the method is called. 为了找出答案,我们必须研究如何调用该方法。 Since it is called as dog.makeSound() , this refers to dog . 由于它被称为dog.makeSound()this它是指dog

The scope the arrow function gets declared in is the scope of the function surrounding it ( dog.makeSound ), not the function the arrow function gets passed to. 箭头函数所声明的作用域是包围它的函数的范围( dog.makeSound ),而不是箭头函数所传递给的函数的范围。

Whe you call dog.makeSound() , this inside of the makeSound function refers to dog , thus it does so inside the arrow function too. WHE你打电话dog.makeSound() this在内部makeSound功能是指dog ,因此箭头函数中这样做了。

  // no matter what the surrounding is ...
  const that = this;
  /*no matter whats here*/(() => {
     console.log(that === this); // this will always be true
  })();

Interestingly, the whatIsThis method returns the Timeout object and not the global object. 有趣的是,whatIsThis方法返回Timeout对象,而不是全局对象。 I am confused on this as well. 我对此也感到困惑。

Me too. 我也是。 That behaviour is strange, are you sure that you are not missinterpreting the consoles output? 这种行为很奇怪,您确定您不会误解控制台输出吗?

Actually its not that it is unable to access the global but the problem is that setTimeout has it's own scope so it is just overcoming the global this. 实际上不是它不能访问全局变量,而是问题在于setTimeout具有它自己的作用域,因此它只是克服了全局变量。

What you can do is : 您可以做的是:

let self = this;
const dog = {
  name: 'fluffy',
  type: 'dog',
  sound: 'woof!',
  makeSound: function() {
    setTimeout(() => {
      console.log("makeSound", self )
    }, 1000)

  },
  whatIsThis: function() {
    setTimeout(function() {
      console.log("whatisthis", this)
    }, 1000)
  }
}


dog.makeSound() // returns dog obj
dog.whatIsThis() // returns Timeout obj
setTimeout(()=>{
  console.log("global", this)
}, 1000);

I hope this will solve your problem of global scope.Hope it helps you. 我希望这能解决您的全球范围问题。希望对您有所帮助。

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

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