【问题标题】:How is 'this' resolved in Array.prototype.forEach when an arrow function in provided?当提供箭头函数时,如何在 Array.prototype.forEach 中解决“this”?
【发布时间】:2019-07-13 19:17:51
【问题描述】:

这是我的代码:

class Employee {
  constructor(ename) {
    this.ename = ename;
  }
}

class EmployeeRenderer {
  constructor(employees) {
    this.employees = employees;
    this.ename = "EmployeeRenderer";
  }
  renderWithArrowFunc() {
    this.employees.forEach(emp => {
      console.log(this.ename); // Will print EmployeeRenderer 3 times
    })
  }
}


var employees = [
  new Employee('Alex'),
  new Employee('Bob'),
  new Employee('Smith')
];

var employeeRenderer = new EmployeeRenderer(employees);
employeeRenderer.renderWithArrowFunc();

我们知道,在箭头函数中,this 不是声明的变量,因此要解析对this 的引用,JavaScript 会咨询封闭范围。因此,在上面的代码中,当console.log(this.ename) 被执行时,JavaScript 询问第一个直接封闭的词法范围——函数forEach——关于this。在 forEach implementation** 中,this 指向调用函数的数组的值:employees 并且因为它没有 ename 属性,所以我希望看到 undefined 3输出中的次数比EmployeeRenderer。它显示this 已解析为EmployeeRenderer.ename。我在这里想念什么?

** 我搜索了forEach 的实现,但找不到,因此我认为它必须与MDN 中提到的pollyfill 相同。

【问题讨论】:

  • 我将您的代码转换为 sn-p 并注销 undefined, undefined, undefined
  • @NicholasTower 糟糕,我犯了太多错误。修复并更新了问题。谢谢。
  • "第一个直接封闭词法范围 - 函数 forEach" - 不,函数调用不会引入 词法范围。并且肯定不是被调用函数的实现
  • @Bergi 但是forEach 有一个声明,所以它为它创建了一个嵌套范围。我错了吗?
  • 但是在你的代码中,forEach没有被声明,箭头函数也没有在forEach的实现中定义。它只是作为参数传递给调用。

标签: javascript foreach arrow-functions lexical-scope


【解决方案1】:

变量范围是词法forEach的代码与确定回调函数中变量的范围无关。它只是在文本上包含箭头函数定义的代码,以及围绕它的块,等等。

所以this 指的是用于调用returnWithArrowFunct() 的上下文,它是employeeRenderer 变量的值。

【讨论】:

  • 更准确地说,它只是文本上包含箭头函数定义的代码(通常作为forEach调用的参数,但不一定)。
  • 没错,我指的是这个特定的示例代码,它们是相同的。但我已经编辑过了。
  • 我还是不明白。 this 是如何解决的?不是lexically解决了吗?
  • @Hans 我建议你阅读stackoverflow.com/questions/500431/…
  • @Bergi 现在我明白了!函数调用链与词法范围无关。后者只是关于函数声明。
【解决方案2】:

this 没有属性ename 并指向外部this。要获得价值,您需要采取emp.ename

class Employee {
  constructor(ename) {
    this.ename = ename;
  }
}

class EmployeeRenderer {
  constructor(employees) {
    this.employees = employees;
  }
  renderWithArrowFunc() {
    this.employees.forEach(emp => {
      console.log(emp.ename); // Will print Alex, Bob, Smith
    })
  }
}


var employees = [
  new Employee('Alex'),
  new Employee('Bob'),
  new Employee('Smith')
];

var employeeRenderer = new EmployeeRenderer(employees);
employeeRenderer.renderWithArrowFunc();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-22
    • 2019-02-19
    • 2023-02-04
    • 1970-01-01
    • 2023-03-15
    • 2017-12-06
    • 1970-01-01
    相关资源
    最近更新 更多