【问题标题】:Arrow function in setTimeout doesn't set window as thissetTimeout 中的箭头函数不会将窗口设置为此
【发布时间】:2020-08-23 22:53:52
【问题描述】:

我有一些由装饰器分配的对象的方法(这就是函数 f 和 ms 的来源)。

  function() {
        setTimeout(() => f.apply(this, arguments), ms); 
      };

'this' 在这里指的是对象。但是 setTimeout 的“this”是窗口,而不是那个对象。如果箭头函数的“this”是从词法上获取的,那么为什么它不是从 setTimeout 中获取的呢?毕竟在下面的代码中:

let user = {
  firstName: "Ilya",
  sayHi() {
    let arrow = () => alert(this.firstName);
    arrow();
  }
};

user.sayHi(); // Ilya

'this' 取自上面的函数。因此,如果该函数在第一种情况下是 setTimeout,为什么两种情况不一样?我认为这可能与在一种情况下作为参数传递的函数有关,在另一种情况下作为局部变量传递,但这在词法环境中不会归结为相同吗?

为什么会有差异?

另外,测试一下:

let obj = {name : "Jeff"};
let obj2 = {name : "Bart", fun2 : function(fun){fun();}};

obj.name2 = obj2.fun2(() => alert(this.name));

但现在我没有收到“Bart”警报,而是一个空字符串。当我用长度替换“名称”时,我只得到 0,“this”指的是窗口。

为什么不能按预期工作?

【问题讨论】:

  • 您已将箭头函数作为回调函数传递给setTimeout,因此此回调中的this 将引用封闭范围内的this,即对象的方法。函数使用定义它们的作用域,而不是调用它们的作用域。您传递给setTimeout 的箭头函数未在setTimeout 中定义。
  • "'this' 在这里指的是对象。但是 setTimeout 的 'this' 是窗口",this 从未设置为任何对象,而是指向窗口对象。
  • 我的意思是setTimeout是window的一个方法,所以我以为箭头函数会在setTimeout里面声明,从而导致setTimeout作为'this'值的来源

标签: javascript this


【解决方案1】:

如果箭头函数的'this'是从词法上获取的,那它怎么不是从setTimeout中获取的呢?

词法意味着作用域取自函数声明的地方,而不是传递给它的地方。

【讨论】:

  • 但是函数不会只是在正在执行的 setTimeout 内声明吗?
  • 它没有在setTimeout 中声明。你看的不是setTimeout的源代码。它在函数表达式中声明,从第一个代码块的第 1 行开始,然后作为参数传递给setTimeout
  • 那么这是否意味着任何作为参数传递的箭头函数都不会被声明为执行函数的局部变量,而是在它之前?
  • 是的,我就是这么说的。
  • 函数表达式也是这样吗?
【解决方案2】:

在函数内部,this的值取决于函数的调用方式。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

function f1() {
  return this;
}

// In a browser:
f1() === window; // true

在您的函数中,您已将 window 对象传递给 setTimeout。

如果你改变你的函数并只传递参数,你将得到对象:

function f() {
  console.log(this);
};

function a (){
  setTimeout(() => f.apply([1]), 1000); // here this = [1]
}

a();  // Array [1]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2016-12-22
    • 1970-01-01
    • 2022-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多