【问题标题】:How do you (best) access 'this' in an object method passed as callback [duplicate]您如何(最好)在作为回调传递的对象方法中访问“this”[重复]
【发布时间】:2018-06-09 16:11:14
【问题描述】:

我正在编写一个简单的文字游戏来练习我的 javascript(我是新手),使用 NPM 包 prompt (https://www.npmjs.com/package/prompt) 在我需要回复时查询用户。

由于我来自 OOP 背景(使用其他语言),我一直在尝试将不同的功能封装在不同的对象中。所以我在一个对象中拥有所有prompt 相关代码,就像这样

function Prompter() {

    this.getUserName = function (callback) {

        var schema = {
            properties: {
                name: {
                    description: "Tu nombre por favor:",
                    pattern: /^[ñÑa-zA-Z\s\-]+$/,
                    message: 'Solo letras, por favor',
                    required: true
                }
            }
        };
        prompt.get(schema, callback);
    };
}

和像这样的另一个对象中的游戏逻辑(这是代码的相关部分)

function Game() {

    this.qGenerator = null;
    this.prompter = null;
    this.user = "";

    this.doNextRound = function () {
       //// omitted for brevity
    };

    this.init = function () {
        this.qGenerator = new QuestionGenerator();
        this.prompter = new Prompter();
    };

    this.startGame = function () {
        this.prompter.getUserName(this.storeUserName);
    };

    this.storeUserName = function (err, result) {
        if (err) {
            this.handleErr(err);
            return;
        }
        this.user = result.name;
        this.doNextRound();
    };
}

然后我就这样开始游戏

const game = new Game();
game.init();
game.startGame();

我遇到的问题是在Game 方法storeUserName 中,我作为回调传递给prompt,我无法通过this 访问Game 对象,因此,当我打电话时

this.doNextRound

storeUserName我明白了

TypeError: this.doNextRound is not a function

我明白为什么,因为this 指的是回调中的节点。但我不知道如何在我作为回调传递的方法中保留对正确this 的引用。我了解如何在更“香草”的 Javascript 中做到这一点——使用 that = thisapply 等,但我不确定在 Node 回调中处理 this 的最佳方法是什么时候通过另一个对象的方法。非常感谢任何建议。

【问题讨论】:

  • 谁标记了这个重新打开应该解释为什么它应该被重新打开。投票保持关闭。

标签: javascript node.js callback this


【解决方案1】:

使用Function.prototype.bind:

this.prompter.getUserName(this.storeUserName.bind(this));

arrow function

this.prompter.getUserName( _ => this.storeUserName() );

其中任何一个都可以。

【讨论】:

  • 谢谢!当我看到它时,第一个是显而易见的。如果你有时间,你能解释一下第二个答案吗?我知道这是一个箭头函数,带有一个未使用的输入参数_,但第二部分让我有点困惑。没有括号,这表示箭头函数的返回值。那么箭头函数返回的是this.storeUserName(),也就是说箭头函数返回的是调用this.storeUserName的结果?这就是作为回调传递的内容?原谅我的无知......
  • @Cerulean 箭头函数回调,它没有在该行被调用。这看起来像:(_ => this.storeUserName())()。因此,稍后调用回调时,将调用箭头函数,然后使用正确的 this 上下文调用 this.storeUserName()
  • @Cerulean 它类似于this.prompter.getUserName( function ( ) { return this.storeUserName() } );,但这不起作用,因为常规函数每次被调用时都会获得自己的this,具体取决于它们的调用方式。箭头函数没有它自己的this,所以里面的this 和定义函数时的一样。要使常规匿名函数的行为类似于箭头函数,您需要 .bind(this) 如果您想支持仅 ES5 的 JavaScript 引擎(在箭头函数被添加到语言之前),您可以这样做。
  • 这个链接描述了我在说什么:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 谢谢——我明白了。我已经习惯了回调——我多年来一直用另一种语言使用它们。我一直认为它是调用 next 的函数——但是当我看到以下内容时,即使是 ES5 形式,this.prompter.getUserName( function ( ) { return this.storeUserName() } ) 我有点被甩了。我想 this form 表达的不仅是接下来要调用哪个函数,而且实际上是 calling 那个函数。我会看看你提供的参考资料。再次感谢!
猜你喜欢
  • 2011-06-20
  • 2018-03-26
  • 2021-03-06
  • 2015-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 2015-03-31
相关资源
最近更新 更多