11

我正在使用 ES6 类在 Node.js 中将一些功能捆绑在一起。这是(基本上)它的样子:

class processDocs {
  constructor(id) {
    this.id = id;
    // console.log(this) returns { id: id }
  }

  getDocs(cb) {
    // console.log(this) returns null
    docs
      .query(qb => {
         qb.where('id', this.id);
      })
      .fetch()
      .then(function(documents) {
        cb(null, documents);
      })
    ;
  }

  alterDocs(documents, cb) {
    //some logic
  }

  reindexSearch(cb) {
    //some logic
  }

  process() {
    // console.log(this) returns { id: id }
    async.waterfall([
      this.getDocs,
      this.alterDocs,
      this.reindexSearch
    ]);
  }
}


export default processDocs;

我认为对于 ES6 类,分配公共变量的方式是简单地引用this,而通过构造函数初始化这些变量的方式正是它在我的类定义中的显示方式。

这是我调用类的方式(在单独的文件中):

var Processor = require('./processDocs');

var pr = new Processor(id);
var docs;
pr.process();

这就是问题所在,当我从构造函数中console.log出来时this,我得到了{ id: id }预期的值;this但是,每当我在运行时注销getDocsprocess,它都是空的。this但是,当我在瀑布之前注销时process(),我得到了我的原始对象。

这有什么原因吗?

顺便说一句,我正在使用 node:v0.10.33和 babel-node并且我使用标志4.6.6运行 babel-node 。--harmony在有人问之前,由于主要依赖项卡在v0.10.x.

编辑我能够创建一个解决方法,但它不是很像 es6。问题似乎与async.waterfall. 我不得不使用 a.bind来修复它:

    async.waterfall([
      this.getDocs.bind(this),
      this.alterDocs.bind(this),
      this.reindexSearch.bind(this)
    ]);
4

4 回答 4

6

ES6 并没有改变“this”的工作方式,因此它取决于“你在哪里调用它”而不是“总是具有相同”的值的上下文。这是非常不直观的,在其他语言中并不常见。

考虑这个例子

class processDocs {
  constructor(id) {
    this.id = id;
    console.log(this)
  }

  getDocs(cb) {
    console.log(this)
  }

  alterDocs(documents, cb) {
    //some logic
  }

  reindexSearch(cb) {
    //some logic
  }

  process() {
    console.log(this)
  }
}

var process = new processDocs(10);
var docs = process.getDocs(function(){});
var processInstance = process.process();

var docsAsFunction = process.getDocs;
docsAsFunction(function(){});

输出是

processDocs {id: 10}
processDocs {id: 10}
processDocs {id: 10}
undefined

如您所见,最后一个是 undefines,它调用“docsAsFunction”,因为您没有直接从其类中调用该函数,因此上下文不同。

例如,您可以在此处阅读有关它的信息

于 2016-05-29T08:27:55.220 回答
1

您可以在类中使用箭头函数,因为它们会自动绑定 this。您可以将类方法编写为:

 getDocs = (cb) => {
    // console.log(this) will not returns null
    docs
      .query(qb => {
         qb.where('id', this.id);
      })
      .fetch()
      .then(function(documents) {
        cb(null, documents);
      })
    ;
 }

请参阅此 MDN 文章:“箭头函数捕获封闭上下文的 this 值”

于 2016-05-29T07:25:55.517 回答
1

考虑将正文更新为process()

process() {
  // console.log(this) returns { id: id }
  async.waterfall([
    (cb)=>{this.getDocs(cb);},
    (documents,cb)=>{this.alterDocs(documents,cb);},
    (cb)=>{this.reindexSearch(cb);}
  ]);
}

使用箭头函数可确保使用正确的上下文调用类的成员函数。

于 2016-05-29T07:50:05.767 回答
0

我为自己创建了以下功能。

let bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; //from coffeescript's => operator

//use in a class's constructor to make the this pointer always refer to the object in which a function resides
function fixThisPointer(_this, func){
  _this[func.name] = bind(_this[func.name], _this);
}

function fixThisPointer2(_this, funcNameArray){
  for (name of funcNameArray){
    _this[name] = bind(_this[name], _this);
  }
}

然后,当我需要它时,我在构造函数中使用这个命令

fixThisPointer(this, foo)

或者这个命令

fixThisPointer2(this, ['foo', 'foo2', 'foo3'])
于 2015-04-17T20:48:56.130 回答