使用 Promise 时,为什么在类方法中未定义“this”?

IT技术 javascript node.js promise this q
2021-01-25 00:44:57

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

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

4个回答

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

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

或者如果你必须按照 ES6 之前的方式来做,你需要在this之前保留

var that = this;
// ...
.then(function() { that.method2() })
被低估的解释,在设置 Promise 时遇到了很多困难,现在是 fixex。谢谢
2021-03-22 00:44:57
我用了 .then(data => this.method(data))
2021-03-26 00:44:57
很好的答案 - 或 ES6 之前的“.then(this.method2.bind(this))”
2021-03-30 00:44:57
FAR FAR 更简单的方法: .then(( foo = this) => {... //then 使用 foo 而不是 this [也转换为 pre-es6 版本] 只要确保它没有被覆盖!
2021-03-30 00:44:57

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

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

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

对于method1,您正在调用method1this.method1()这种调用方式在作为this您的实例对象的上下文中调用它这就是为什么里面的上下文method1是实例。

现在,是一个答案帮助我了解
2021-04-06 00:44:57

基本上,您传递给它的是一个没有上下文引用的函数引用。this上下文在几个方面决定:

  1. 含蓄地。调用全局函数或没有绑定的函数假定全局上下文。*
  2. 通过直接引用。如果你打电话,myObj.f()那么myObj将成为this上下文。**
  3. 手动装订。这是您的函数类,例如.bindand .apply这些您明确说明this上下文是什么这些总是优先于前两个。

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

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

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

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

function then( callback ) {

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

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