在JavaScript中使用装饰器时箭头函数和函数之间的区别

在JavaScript中使用装饰器时箭头函数和函数之间的区别,javascript,function,this,settimeout,arrow-functions,Javascript,Function,This,Settimeout,Arrow Functions,我对JavaScript有点陌生,目前正在研究动态范围如何工作。现在我明白了这个是如何得到它的值的。我已经阅读了所有的规则并理解了其中的大部分,但是我很难理解这段代码,它解释了在装饰器中使用箭头函数和函数之间的区别。 这是代码的链接 带有箭头函数的代码 function defer(f, ms) { return function() { //What is this? Why use apply? setTimeout(() => f.apply(this, arg

我对JavaScript有点陌生,目前正在研究动态范围如何工作。现在我明白了
这个
是如何得到它的值的。我已经阅读了所有的规则并理解了其中的大部分,但是我很难理解这段代码,它解释了在装饰器中使用箭头函数和函数之间的区别。
这是代码的链接

带有箭头函数的代码

function defer(f, ms) {
  return function() {
    //What is this? Why use apply? 
    setTimeout(() => f.apply(this, arguments), ms)
  };
}

function sayHi(who) {
  alert('Hello, ' + who);
}

let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // Hello, John after 2 seconds

功能正常

function defer(f, ms) {
  return function(...args) {
    // What's the purpose of this line? 
    let ctx = this;
    setTimeout(function() {
     // Again why apply? 
      return f.apply(ctx, args);
    }, ms);
  };
}
这是我难以理解的

  • 为什么我们在这两种情况下都使用
    apply
    ?我们不能不申请就做吗
  • 如果我只是调用
    f
    而不是使用
    f.apply
    ,会发生什么
  • 我们使用
    apply
    是因为
    setTimeOut

    任何解释都将不胜感激。

    实实在在的问题——老实说——这是你思考的好迹象

    为什么我们在这两种情况下都使用apply?我们不能不申请就做吗

    值得一提的是,
    .apply
    (及其同级
    .bind
    )来自我们没有自动绑定“this”上下文的箭头函数的时代。所以,你要知道,他们来自于更古老的时代

    现在,它们的用途是什么(应用/绑定)?只有当您想分配“this”时才需要它们。在您介绍的案例中,您没有引用
    ——这意味着如果您只是正常调用函数,您将得到相同的结果。这也解决了你的问题:

    如果我只是调用f而不是使用f.apply,会发生什么

    没什么。你也会有同样的结果

    由于setTimeOut,我们使用apply吗

    看起来你正在举一些你在互联网上看到的例子,但简单的回答是:是的,你会使用<由于setTimeOut的原因,代码>时应用
  • 绑定
    。但您提供的示例隐藏了实际的教训

    这是一个尝试

    
    函数iReferenceThisForStuff(){
    console.log(this.foo)
    }
    设置超时(iReferenceThisForStuff,10)
    //…10毫秒通行证
    //“未定义”被记录,因为“this”引用全局窗口对象
    
    在上面的示例中,我们向超时传递了一个非绑定函数,并记录了
    window.foo
    ,因为-当未明确设置时-
    是对全局范围的引用。这是一种回退行为,非常奇怪——但它是如何工作的

    使用
    .bind
    .apply
    示例:

    
    函数iReferenceThisForStuff(){
    console.log(this.foo)
    }
    setTimeout(IRereferenceThisforStuff.bind({foo:bar}),10)
    //…10毫秒通行证
    //记录“bar”是因为“this”引用了传递给“.bind”的对象引用`
    //你也可以做。。。
    setTimeout(函数(){
    返回iReferenceThisForStuff.apply({foo:“bar”},/*可能还有一些附加参数*/)
    }, 10)
    //你也会有同样的结果。
    
    关于箭头函数的最后说明。它们将
    this
    绑定为实例化它们的闭包中的
    this

    (function () {
       setTimeOut(() => { // This arrow function is instantiated in a closure where `this` is a reference to { foo: "bar" } and is automatically bound.
           console.log(this.foo) // Will eventually log "bar"
       })
    }.bind({ foo: "bar" }))
    

    使用
    apply
    的目的是控制
    将是什么。因为setTimeout和setInterval调用的函数没有其this集,因此在严格模式下它将是未定义的,否则将是全局对象。延迟函数将延迟函数的this设置为与调用延迟函数时使用的this相同,因此调用方可以在延迟函数中控制this的值。“未显式设置时-这是对全局范围的引用”否,这是对全局对象本身的引用,在严格模式下,它是未定义的这实际上与作用域无关,因为它总是在当前执行上下文中解析的。除了arrow函数,当它通过词法作用域链解析为外部执行上下文的这一部分时。