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

时间:2019-08-23 13:14:15

标签: javascript ecmascript-6 this settimeout arrow-functions

我正在尝试使用此功能和箭头功能。 在setTimeout中遇到箭头函数的词法范围方面的麻烦。

makeSound方法将其作为dog对象返回。为什么因为箭头函数位于setTimeout方法内部,所以它不采用全局对象的范围?有趣的是,whatIsThis方法返回Timeout对象,而不是全局对象。我对此也感到困惑。

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

3 个答案:

答案 0 :(得分:0)

  

为什么箭头功能位于setTimeout方法内部,为什么它不占用全局对象的范围?

回调不在setTimeout函数的内部。它作为参数{em>传递给setTimeout函数。

考虑以下等效代码:

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

此代码的行为完全相同。唯一的不同是,回调函数在传递给setTimeout之前先分配给变量。

这应该证明箭头功能不是在setTimeout内部,而是在makeSound内部。箭头函数像其他变量一样,按词法解析this。因此,我们必须找出thismakeSound的值是什么。为了找出答案,我们必须研究如何调用该方法。由于它被称为dog.makeSound(),所以this指的是dog

答案 1 :(得分:-1)

箭头函数所声明的作用域是包围它的函数 dog.makeSound)的作用域,而不是箭头函数所传递给的函数。

在调用dog.makeSound()内的this时,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方法返回Timeout对象,而不是全局对象。我对此也感到困惑。

我也是。这种行为很奇怪,您确定您不会误解控制台输出吗?

答案 2 :(得分:-2)

实际上不是不是它无法访问全局变量,而是问题在于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);

我希望这能解决您的全球范围问题。希望对您有所帮助。