为啥在使用 Promise 时在类方法中未定义“this”? [复制]

Posted

技术标签:

【中文标题】为啥在使用 Promise 时在类方法中未定义“this”? [复制]【英文标题】:Why is 'this' undefined inside class method when using promises? [duplicate]为什么在使用 Promise 时在类方法中未定义“this”? [复制] 【发布时间】:2016-04-28 02:42:20 【问题描述】:

我有一个 javascript 类,每个方法都返回一个 Q 承诺。我想知道为什么thismethod2method3 中未定义。有没有更正确的方法来编写这段代码?

function MyClass(opts)
  this.options = opts;

  return this.method1()
    .then(this.method2)
    .then(this.method3);


MyClass.prototype.method1 = function()
  // ...q stuff...

  console.log(this.options); // logs "opts" object

  return deferred.promise;
;

MyClass.prototype.method2 = function(method1resolve)
  // ...q stuff...

  console.log(this); // logs undefined

  return deferred.promise;
;

MyClass.prototype.method3 = function(method2resolve)
  // ...q stuff...

  console.log(this); // logs undefined

  return deferred.promise;
;

我可以使用bind 解决这个问题:

function MyClass(opts)
  this.options = opts;

  return this.method1()
    .then(this.method2.bind(this))
    .then(this.method3.bind(this));

但不完全确定为什么需要bind.then() 杀死 this 关闭了吗?

【问题讨论】:

当您使用 bind() 时,它会创建另一个函数,其范围与您将通过参数传递的范围完全相同。虽然它只回答了您的最后一个问题,但请查看 Mozila 的文档:developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/… 用 8 个词解释 this 是如何与 that 重复的?我刚刚提出了同样的问题,that 将 回答。我已经知道that,但我正在接受承诺、ES6 类和this @Paulpro 不太确定这应该被标记为setTimeout issue 的副本;因为问题以两种完全不同的方式出现。希望在 Promise 的上下文中解决他们的this 范围问题的人们会立即被指向一个更间接的问题,其中接受的答案使用 2009 年的反模式。2 + 2 = 4 !== ((8+2)*6)/15 = 4 IMO 绝对不应该被标记为重复,尤其是关于超时的问题。这个问题专门关于 Promises 和答案是上帝派来的。谢谢。 【参考方案1】:

this 始终是调用该方法的对象。但是,当将方法传递给then() 时,您并没有调用它!该方法将存储在某个地方并稍后从那里调用。如果你想保留this,你必须这样做:

.then(() => this.method2())

或者如果你必须使用pre-ES6的方式,你需要保留this之前:

var that = this;
// ...
.then(function()  that.method2() )

【讨论】:

很好的答案 - 或 pre-ES6 ".then(this.method2.bind(this))" 我用过.then(data => this.method(data)) FAR FAR 更简单的方法:.then(( foo = this) => ... //然后使用 foo 而不是 this [也转换为 es6 之前的版本] 只要确保它不是覆盖! 被低估的解释,在设置 Promise 时遇到了很多困难,现在是 fixex。谢谢【参考方案2】:

默认情况下,Promise 处理程序在全局对象 (window) 的上下文中调用。当处于严格模式 (use strict;) 时,上下文为 undefined。这就是 method2method3 发生的事情。

;(function()
  'use strict'
  Promise.resolve('foo').then(function()console.log(this)); // undefined
());

;(function()
  Promise.resolve('foo').then(function()console.log(this)); // window
());

对于method1,您将method1 称为this.method1()。这种调用方式是在 this 对象的上下文中调用它,该对象是您的实例。这就是为什么method1 中的上下文是实例。

【讨论】:

现在this是一个帮助我理解it的答案。【参考方案3】:

基本上,您传递给它的是一个没有上下文引用的函数引用。 this 上下文通过以下几种方式确定:

    隐式。调用全局函数或没有绑定的函数假定全局上下文。* 直接参考。如果您调用myObj.f(),那么myObj 将成为this 上下文。** 手动绑定。这是您的函数类,例如.bind.apply。这些您明确说明this 上下文是什么。这些总是优先于前两个。

在您的示例中,您传递了一个函数引用,因此在调用它时,它暗示它是一个全局函数或一个没有上下文的函数。使用 .bind 通过创建一个新函数来解决这个问题,其中 this 被显式设置。

*这只适用于非严格模式。在严格模式下,this 设置为 undefined

**假设你使用的函数没有被手动绑定。

【讨论】:

【参考方案4】:

函数获取其上下文 (this) 的一种方式是来自调用它们的对象(这就是为什么 method1 具有正确的上下文 - 它是在 this 上调用的)。您将对函数本身的引用传递给then。你可以想象then 的实现看起来是这样的:

function then( callback ) 

  // assume 'value' is the recently-fulfilled promise value
  callback(value);

在该示例中,callback 是对您的函数的引用。它没有任何上下文。正如您已经注意到的,您可以通过在将函数传递给 then 之前将函数绑定到上下文来解决这个问题。

【讨论】:

以上是关于为啥在使用 Promise 时在类方法中未定义“this”? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

`data` 在 apollo useMutation Promise 中未定义

React-Router:为啥react中未定义useHistory? [复制]

C++中static函数类外定义的时候为啥不写static?

Python 元类:为啥在类定义期间不调用 __setattr__ 来设置属性?

为啥声明类型时可以在 redux 中未定义状态?

JAXB:为啥在生成的 xml 文档中未使用定义的命名空间前缀?