【问题标题】:What is the mechanism for lexical scope binding inside object methods (Javascript)?对象方法(Javascript)内的词法范围绑定的机制是什么?
【发布时间】:2019-10-23 14:34:05
【问题描述】:

我在理解箭头函数和词法作用域时遇到了严重的大脑冻结:前段时间我通读了 Kyle Simpson 的所有“你不知道 JS”,我认为我很好地理解了作用域和上下文。但我只是不明白箭头函数词法范围是如何应用于对象的——我一直在使用 React 中的类,并且总是很清楚箭头函数绑定到的 this 是类。

例如,在这个例子中(来自https://medium.com/tfogo/advantages-and-pitfalls-of-arrow-functions-a16f0835799e

 let obj = {
      myVar: 'foo',

      myFunc: function() { 
        console.log(this.myVar)  

        setTimeout(() => {
          console.log(this.myVar)
        }, 1000)
      }
    }

箭头函数应该正确绑定this,避免使用bind。但这来自词法范围?凭什么?因为下一个作用域是函数myFunc的作用域,而这个函数的词法父作用域是obj

然后他们给出了这个例子

let obj = {
  myVar: 'foo',

  myFunc: () => { 
    console.log(this.myVar)  
  }
}
obj.myFunc() // undefined

this 的正确绑定不会发生。这是因为没有围绕箭头函数的函数,所以下一个词法范围是全局上下文?

总结一下:这里的“词法作用域”是否真的就是函数定义的同一个词法作用域,而带有箭头函数的this 只是为了寻找下一个包含函数的父函数?

我向你保证,我不久前就理解了这一点(或认为我理解了),但我猜是“使用它或失去它”——

【问题讨论】:

    标签: javascript scope arrow-functions


    【解决方案1】:

    箭头函数与所有其他函数具有相同的词法范围规则,this 除外。当您定义箭头函数时,它会在定义时捕获 this 现在的内容,并永远使用它。箭头函数中的 thisin the lexical context of the arrow function's definition is the permanent value ofthis` 可用的值。

    一种思考方式:如果我结束了这个箭头函数定义,并且在定义之外立即使用了this,那么this 的值会是什么?

    在第二种情况下,考虑一个额外的属性:

    let obj = {
      myVar: 'foo',
    
      myFunc: () => { 
        console.log(this.myVar)  
      },
    
      myOtherVar: this.myVar
    }
    

    除了myOtherVar 之外,我们肯定是undefined,因为当您构建这个对象时,thiswindow,它没有myVar 属性。箭头函数也一样:它永久采用windowthis,所以this.myVar是未定义的。

    【讨论】:

    • 谢谢——我想它现在又回来了。因此,与其说是“词法范围”,不如说是this在定义/解析箭头函数时?因此,第一个函数起作用的唯一原因是,this 在定义箭头函数时在运行时具有 obj 的值,并且由于调用 obj.myFunc 而具有此值?
    • @Cerulean 正确:在第一种情况下,myFunc 是一个非箭头函数(myFunc: function() {....). The arrow function is defined within the execution of that non-arrow func, whose execution has a this` 值不同于 this 是定义对象时。
    【解决方案2】:

    但这来自词法范围?在什么意义上?

    从某种意义上说,它与 this 在定义箭头函数的函数内部具有相同的值。

    console.log(this.myVar) 使用相同的this

    因为下一个作用域是函数 myFunc 的作用域,而这个函数的词法父作用域是 obj?

    myFunc 的父作用域无关紧要。它不是箭头函数。它从调用它的位置获取其this 值。


    没有正确绑定 this 的地方。

    this 与父函数相同。对象字面量对其没有影响。

    如果我们添加另一个 console.log,那么两者(再次)引用相同的值。

    console.log(this.myVar)
    let obj = {
      myVar: 'foo',
    
      myFunc: () => { 
        console.log(this.myVar)  
      }
    }
    

    【讨论】:

      【解决方案3】:

      首先要记住箭头函数的定义

      箭头函数没有自己的this;使用封闭执行上下文的 this 值 (mozilla)


      let obj = {
        myVar: 'foo',
        myFunc: function() { 
          console.log(this.myVar)  
          setTimeout(() => {
            console.log(this.myVar)
          }, 1000)
        }
      }
      obj.myFunc();

      箭头函数应该正确绑定 this,避免绑定。 但这来自词法范围?凭什么?因为下一个范围 是函数 myFunc 和该函数的词法父级的函数 范围是obj?

      这里 setTimeout 回调的封闭函数是对象本身的一个方法,因此它会继承当前实例,如您所说。


      let obj = {
        myVar: 'foo',
        myFunc: () => { 
          console.log(this.myVar)  
        }
      }
      obj.myFunc() // undefined

      没有正确绑定 this 的地方。这是因为有 没有围绕箭头函数的函数,所以下一个词法 scope 是全局上下文吗?

      在第二种情况下,实例上声明的方法使用箭头函数,因此 this 将从封闭函数继承,但由于没有函数包装,您的对象将是 Window

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-23
        • 2013-06-05
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 2022-07-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多