【问题标题】:Weird way ES6 class method, arrow function and this works奇怪的方式 ES6 类方法,箭头函数,这有效
【发布时间】:2021-03-23 00:42:59
【问题描述】:

我在输入问题时发现了这个疑问,但我认为为未来的开发人员记录这一点仍然有意义。

寻求帮助以了解以下输出:(主要是案例 4 与案例 5)

var obj1 = {
  x:1,
  getX: function () {
    const inner = () => {
      console.log('1:',this.x);
    }
    inner();
  }
}
obj1.getX();

var obj2 = {
  x:1,
  getX() {
    const inner = () => {
      console.log('2:',this.x);
    }
    inner();
  }
}
obj2.getX();

var obj3 = {
  x:1,
  getX: () => {
    const inner = () => {
      console.log('3:',this.x);
    }
    inner();
  }
}
obj3.getX();

function a() {
  this.x = 1;
  function b() {
    console.log('4: ', this.x);
  }
  b();
}
a();

var obj5 = {
  x: 1,
  getX() {
    const inner = function() {
      console.log('5: ',this.x);
    }
    inner();
  }
}
obj5.getX();

剧透警告!!!以下是我的猜测和解释!!! 在进一步阅读之前,最好自己尝试一下。

我的理解:

案例1:由于inner是一个箭头函数,所以考虑了parent的this。因此1 是有道理的。

案例 2: 从语义上看,案例 1 和案例 2 之间没有任何区别。如果我在这里错了,请纠正我。

也就是说,{getX(){}} 与 {getX: function(){}} 应该是等价的。

案例 3: 由于 inner 和 getX 都是箭头函数,this 代表窗口范围,因此输出应为 undefined。

案例4:由于调用内部函数没有关联对象,所以this指的是父方法的this,与a的含义相同。因此,输出为 1。

案例5:由于调用内部函数没有关联对象,所以this是指父方法的this,与obj4obj5相同.因此输出应该是 1。

注意:案例 5 输出为 undefined。需要帮助理解这一点。

注意 2: 在新浏览器选项卡的控制台中,仅复制粘贴案例 5。您将看到 undefined。而如果将所有这些案例复制粘贴在一起,案例 5 的输出将为 1。

【问题讨论】:

  • "案例 4:由于调用内部函数没有关联对象,所以 this 指的是父方法的 this" - 没有。 value of this 由调用 b() 或 a() 确定,它们不传递任何上下文,因此默认为全局对象(使用严格模式!)。
  • 这能回答你的问题吗? Arrow Functions and This
  • @SebastianSimon - 感谢您的评论。我在 Chrome 和 Safari 上再次尝试了不同的场景,然后在我的原始帖子中添加了注释 2。

标签: javascript closures this arrow-functions


【解决方案1】:

您可能只打印出this 而不是this.x,这样更容易理解。案例 1-3 this 指的是obj_n,而案例 4 和 5 指的是 window 全局对象。

this 上下文,对于非箭头正常function() {},在声明时未绑定。直到调用函数时才确定。当函数被调用时,需要明确指定this应该是什么,使用以下之一:

  1. contextObject.methodName() 语法(如果有)
  2. functionName.call(context) 或 functionName.apply(context)

如果没有提供这样的规范,那么在 sloppy 模式下,this 将回退为 window 全局对象,在严格模式下,它将是 undefined。

它没有“引用父方法的this”。

【讨论】:

  • 准确地说inner();(在案例5中位于getX内部)被称为没有上下文,这就是this在@内部的原因987654340@ 函数是window(或globalThis,或在严格模式下undefined)? this 完全来自上下文绑定,而不是来自调用范围,对吗?例如。如果有一个虚构的magicObject 并且调用实际上是magicObject.inner();,那么该函数中的this 将引用magicObject,就像使用inner.call(magicObject) 一样,对吗?
  • 稍微扩展第二段:将函数作为某物的属性是不够的,例如const obj = { x: 1, getX: function(){ return this.x; } }, myGetX = obj.getX; myGetX(); 导致 undefined 因为 myGetX(); 是没有绑定上下文的调用。 obj context got lost 在变量赋值 myGetX = obj.getX 处,尽管您可能会认为 obj 以某种方式“粘”到 getX 因为它已在其中定义 — 但不是:getX 只是一个常规函数不知道obj,除非它被作为上下文调用。
  • @SebastianSimon 是的,你的理解完全正确!
【解决方案2】:

原因:在第5种情况下,由于内部方法在调用时没有与任何对象关联,所以this引用了父方法的this。在这里,父方法的this 表示封装了所有代码的方法的this。我会说这是一个非常有趣的“故障”。

为了更好地理解它:

function main() {
  this.x = 15;
  var obj5 = {
    x: 1,
    getX() {
      const inner = function() {
        console.log('5: ',this.x);
      }
      inner();
    }
  }
  obj5.getX();
}
main();

打印:5: 15

【讨论】:

  • 你可以打印出this而不是this.x,这样更容易理解。案例 1-3 this 指的是 obj_n,而案例 4 和 5 它指的是 window 全局对象。它不“引用父方法的this”。
  • 1.这不是“故障”,而是 this 关键字的工作原理 2. 您的解释具有误导性 - 调用 inner 时的 this 与 main 的 this 之间没有直接链接。碰巧两者都是window,因为两者都不会将this 设置为任何东西,并且代码没有在严格模式下运行。见How to access the correct this inside a callback?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 2019-06-27
相关资源
最近更新 更多