【问题标题】:How to use `this` in a function called by an ES6 arrow function? [duplicate]如何在 ES6 箭头函数调用的函数中使用 `this`? [复制]
【发布时间】:2016-03-06 10:38:47
【问题描述】:

我理解(我认为)ES6 中的箭头函数使用Lexical this,但我不确定为什么一个由胖箭头函数调用的函数会将this 设置为未定义。

我需要做什么才能在handleAuthResult 中调用this.setResult?如果不需要,我不想使用旧的function () {}.bind(this)

"use strict";

class Example {
    constructor() {
        this.checkAuth();
    }

    checkAuth() {
        document.write("Checking auth now. ");
        var iid = setInterval(() = > {
            if (true) { // Have to do some dumb check here
                clearInterval(iid);
                this.authenticate(this.handleAuthResult)
            }
        }, 500);
    }

    authenticate(callback) {
        callback({
            value: true
        });
    }

    handleAuthResult(result) {
        document.write(`The result is ${result.value}.`);
        this.setResult(result, this.loadThePage)
        // ^ `this` is undefined here. How can I ever set the result?
    }

    // Another asynchronous thing
    setResult(result, callback) {
        callback();
    }

    loadThePage() {
        document.write("The code never gets here, but the page should load now. ");
    }
};
var example = new Example();

谢谢! https://jsfiddle.net/vujev4dj/

编辑: 在我为这被标记为重复的辩护中,我期望的行为确实在下面的小提琴中起作用,这就是我期望不必使用的原因ES6 中this.handleAuthResult 上的bind 函数:https://jsfiddle.net/m9e7j4ds/

【问题讨论】:

  • 它在小提琴中起作用的原因是因为它使用React.createClass()而不是使用ES6类(扩展React.Component)。 React.createClass() 绑定所有方法,使用 ES6 类时不会发生这种情况。
  • @bergi 我不同意这是您链接的问题的重复,因为它与将方法绑定到 ES6 类实例的方法无关。特别是,将箭头函数直接设为答案中未提及的类。我相信这就是提问者所要寻找的,尽管这个问题可以提出得更好。

标签: javascript scope ecmascript-6


【解决方案1】:

当你打电话时

this.authenticate(this.handleAuthRequest);

this 丢失了

你可以的

this.authenticate(this.handleAuthRequest.bind(this));

或者

this.authenticate(() => this.handleAuthRequest());

总体而言,代码非常混乱,而且很多部分对我来说没有任何意义。特别是callback({value: true}) 很奇怪。无论如何,如果您有更具体的问题,我很乐意提供帮助。

【讨论】:

  • 关于使用另一个箭头函数的第三个选项的要点。
  • 感谢您的建议。我同意代码很乱,但它实际上是 Google 提供的这个 JavaScript 快速入门的超级简化版本,我用我自己的回调函数替换了它们的函数:developers.google.com/google-apps/calendar/quickstart/…
  • 谢谢@TJ。我经常更喜欢使用另一个箭头函数而不是依靠Function.prototype.bind
  • 更好地使用箭头函数是将其直接放在类上。然后它总是绑定到类的实例上。
【解决方案2】:

thishandleAuthResult 中是undefined,因为handleAuthResult 不是箭头函数,因此没有词法this。它是一个普通的原型函数(大致称为“方法”),这意味着this 是由它的调用方式定义的。

你的称呼方式:

authenticate(callback) {
    callback({
        value: true
    });
}

没有将this 设置为任何特定的值,因此thisundefined(因为您处于严格模式)。

要修复它,请将this 传递给authenticate 并使用它:

this.authenticate(this.handleAuthResult, this)

authenticate(callback, thisArg) {
    callback.call(thisArg, {
        value: true
    });
}

或使用Function#bind 创建一个函数,当调用该函数时,将使用正确的this 调用handleAuthResult

this.authenticate(this.handleAuthResult.bind(this))

为了完整起见,naomik points out a third option which is quite elegant:使用另一个箭头函数:

this.authenticate(() => this.handleAuthRequest())

【讨论】:

  • 我看到你也在这里附加了@naomik 的解决方案。您的回答总体上非常简洁,并解释了我为什么感到困惑。我接受了你的回答:)
【解决方案3】:

checkAuth,你应该使用

this.authenticate(this.handleAuthResult.bind(this))

那是因为调用callback({value: true});时没有绑定this

【讨论】:

  • 另一种方法是将回调方法定义为箭头函数,当应用于类时,总是绑定到它们所在的类。这个问题专门询问箭头函数。