Javascript setTimeout中箭头功能与es5功能的范围

Javascript setTimeout中箭头功能与es5功能的范围,javascript,ecmascript-6,this,settimeout,arrow-functions,Javascript,Ecmascript 6,This,Settimeout,Arrow Functions,我正在试验这个和箭头函数。 在setTimeout中遇到了一些有关箭头函数词法范围的问题 makeSound方法将其作为dog对象返回。既然arrow函数在setTimeout方法中,为什么它不接受全局对象的作用域?有趣的是,whatIsThis方法返回超时对象,而不是全局对象。我对此也感到困惑 const dog={ 名称:'毛茸茸', 键入:“dog”, 声音:“汪!”, makeSound:function(){ 设置超时(()=>{ log(“makeSound”,这个) }, 100

我正在试验这个和箭头函数。 在setTimeout中遇到了一些有关箭头函数词法范围的问题

makeSound方法将其作为dog对象返回。既然arrow函数在setTimeout方法中,为什么它不接受全局对象的作用域?有趣的是,whatIsThis方法返回超时对象,而不是全局对象。我对此也感到困惑

const dog={
名称:'毛茸茸',
键入:“dog”,
声音:“汪!”,
makeSound:function(){
设置超时(()=>{
log(“makeSound”,这个)
}, 1000)
},
这是什么:函数(){
setTimeout(函数(){
log(“whatisthis”,this)
}, 1000)
}
}
dog.makeSound()//返回dog obj
dog.whatIsThis()//返回超时对象
设置超时(()=>{
console.log(“全局”,此)

},1000)//返回全局obj
实际上,这并不是因为它无法访问全局对象,而是因为setTimeout有自己的作用域,所以它只是克服了全局对象

您可以做的是:

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);

我希望这将解决您的全局作用域问题。希望它能帮助您。

箭头函数声明的作用域是它周围函数的作用域(
dog.makeSound
),而不是箭头函数传递到的函数

当您调用
dog.makeSound()
时,
这个
函数中的
makeSound
指的是
dog
,因此它在arrow函数中也是这样做的

  // no matter what the surrounding is ...
  const that = this;
  /*no matter whats here*/(() => {
     console.log(that === this); // this will always be true
  })();
有趣的是,whatIsThis方法返回超时对象,而不是全局对象。我对此也感到困惑

我也是。这种行为很奇怪,您确定没有遗漏对控制台输出的解释吗

既然arrow函数在setTimeout方法中,为什么它不接受全局对象的作用域

回调不在
setTimeout
函数的“内部”。它作为参数传递给
setTimeout
函数

考虑以下等效代码:

const dog = {
  name: 'fluffy',
  type: 'dog',
  sound: 'woof!',
  makeSound: function() {
    const cb = () => console.log("makeSound", this);
    setTimeout(cb, 1000)
  },
}
此代码的行为完全相同。唯一的区别是,回调函数在传递给
setTimeout
之前首先分配给变量

这应该表明箭头函数不是“内部”
setTimeout
,而是“内部”
makeSound
。箭头函数按字典方式解析
这个
,就像其他变量一样。因此,我们必须找出
this
makeSound
中的值。为了找到答案,我们必须看看这个方法是如何被调用的。由于它被称为
dog.makeSound()
这个
指的是
dog

。你确定dog.whatIsThis()记录超时对象。对我来说,它记录窗口对象,这很有意义,因为您声明了一个新的词法范围,该范围由setTimeout调用。arrow函数从外部词法范围(在您的例子中,makeSound等于dog)获取它的this。