【问题标题】:Confused about "this" in arrow function对箭头函数中的“this”感到困惑
【发布时间】:2019-08-22 05:58:42
【问题描述】:

我看到了很多关于这个话题的讨论,也阅读了很多文章,但我仍然对箭头函数中this 所指的内容感到困惑。

我似乎遇到了与以下代码(简化)相关的运行时错误:

export class Foo implements OnInit {
myProp: string;
myKeys: Array<any> = [];
mySubKeys: Array<any> = [];
@Input myObj;

. . . 

ngOnInit() {

this.myKeys = Object.keys(this.myObj); 
this.myKeys.forEach((key) => {
    this.myProp = key;
    this.mySubKeys = Object.keys(this.myObj[key]);
    this.mySubKeys.forEach((subkey) => { . . .  
. . . 

错误发生在this.myProp = key,调试器抱怨this 未定义。

我的困惑是,对于箭头函数,我理解 this 指的是在调用箭头函数的范围之前的 this。在这种情况下,前面的范围不是class,因此不应该定义this.myProp吗?

我尝试将箭头函数更改为 forEach(function(key) { . . . . . . . . . . . 但得到了不同的错误。

最后,如果箭头函数内的this 没有引用class this 那么我如何引用class this 和关联的class 属性(例如@987654339 @) 在箭头函数里面?

【问题讨论】:

标签: javascript angular typescript


【解决方案1】:

您公开的代码中的 this 应该按您的预期工作。 我认为您的问题来自这一行:

this.myKeys = Object.keys(this.myObj) {

当它应该只是一个关闭 ; 时,有一个开口 {

this.myKeys = Object.keys(this.myObj);

代码应如下所示:

ngOnInit() {
    this.myKeys = Object.keys(this.myObj);
    this.myKeys.forEach((key) => {
        this.myProp = key;
        this.mySubKeys = Object.keys(this.myObj[key]);

编辑:

添加演示以尝试 this 正在工作: https://stackblitz.com/edit/stackoverflow-mykeys-demo

请注意,Input() 也必须有 ()。

【讨论】:

  • 非常感谢,丹尼尔。这是一个很好的收获。不幸的是,我在编辑原始代码时错误地在上面的代码中添加了额外的“}”,以使其更易于发布。有问题的原始代码没有额外的“}”。那是我编辑不好的错,很抱歉造成任何混乱。截至目前,似乎 TheParam 的解释是正确的(因为他的解决方案解决了问题),但其他几个人表示我不应该首先遇到问题,而且我的代码中肯定有其他问题,所以我会非常感谢能够深入神秘的核心!
  • 如果您可以以任何方式发布您的代码,也许我们可以为您提供更多帮助。也许它发生是因为 this.myObj 是如何声明的或类似的东西。我将上传一个示例,向您展示它应该如何正常工作并编辑我的答案。
  • 非常感谢,丹尼尔。这很有帮助。关于我的代码,由于它相当复杂,可能需要我一段时间来清理它,所以提前感谢您的耐心等待,也感谢您提供查看它的建议。此外,有点令人困惑的是,我在最近几天更改了代码,现在我无法复制我之前遇到的问题! . . .但是关于您的 Stackbltiz 示例。 . .
  • 是的。参考第一个问题:console.log("I'm working: " + this.allTheSubKeys[subkey]);this.allTheSubKeys 它是一个字符串矩阵,所以如果你想得到一个值,你必须使用索引。 (可以更改foreach添加索引:this.mySubKeys.forEach((subkey,x) =&gt; { console.log("I'm working: " + this.allTheSubKeys[x]); });
  • 参考this.allTheProps,如果您在示例中看到,它可以是两个东西:索引数组或对象键数组。在数组索引的情况下,它可以按您的意愿工作。作为另一种解决方案,如果您在 foreach 中添加索引,它会对您有所帮助。
【解决方案2】:

原因是函数中this的值取决于函数的调用方式。

如果函数被调用为this.myKeys.forEach(),在最基本的层面上,this 的值就是调用上下文,在这种情况下是myKeys

但在所有情况下,它都不会是 myKeys,所以 this.myProp &amp; this.mySubKeys 不会返回 value,它会返回 undefined 或引发错误。

这种不稳定性是 Javascript 中一个非常普遍的问题,从早期就影响了它。

ES5 中,我们可以使用多种方法来稳定this 的值。一种常见的解决方案是将其分配给顶部的另一个变量,通常称为self,然后始终在函数体中使用self,如下所示:

ngOnInit() {


   this.myKeys = Object.keys(this.myObj) {

    let self = this; // declare the variable to refer class object
    this.myKeys.forEach((key) => {
        self.myProp = key;
        self.mySubKeys = Object.keys(this.myObj[key]);
        self.mySubKeys.forEach((subkey) => { . . .  
   . . . 

希望这会有所帮助!

【讨论】:

  • 成功了!非常感谢!现在的问题是,为什么它会起作用?我认为箭头函数应该从封闭的上下文中获取它的this,这应该是classthis,对吧?
  • 我已经更新了答案并附有解释,请检查
  • 谢谢你,TheParam。这非常有帮助。现在困扰我的最后一件事是另一张海报 chiril sarajiu 有一个帖子(自从被撤下)显示 Stackblitz stackblitz.com/edit/angular-9jz39z> 复制了我的代码并显示没有问题。 this 在他的 forEach 块中运行良好,无需声明额外的 self 变量。所以现在我很困惑。我开始认为 Firefox 调试器可能有问题?
  • 为了强化问题,根据ecma-international.org/ecma-262/5.1>“如果在对象上调用函数,例如在 obj.myMethod() 或等效的 obj["myMethod"]() ,然后将 ThisBinding 设置为对象(示例中为 obj;§13.2.1)。” . . .
  • 。 . .这支持 TheParam 的解释,如下所述……“在 Array.prototype 函数的情况下,在执行上下文中调用给定的 callbackfn,如果提供,则 ThisBinding 设置为 thisArg;否则,调用全局对象。”鉴于 forEach 是一个数组原型函数,并且我没有提供 thisArg,这也支持了 TheParam 的解释。 . .
【解决方案3】:

来自 MDN:

箭头函数没有自己的 this。使用封闭词法范围的 this 值;箭头函数遵循正常的变量查找规则。因此,在搜索当前范围内不存在的 this 时,他们最终会从其封闭范围中找到 this。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-19
    • 2021-12-31
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多