为什么在节点中的EventEmitter.prototype.once中使用$ self?

时间:2012-05-20 04:44:37

标签: javascript node.js closures

我正在查看event.js中的once()的实现:

EventEmitter.prototype.once = function(type, listener) {
  if ('function' !== typeof listener) {
    throw new Error('.once only takes instances of Function');
  }

  var self = this;
  function g() {
    self.removeListener(type, g);
    listener.apply(this, arguments);
  };

  g.listener = listener;
  self.on(type, g);

  return this;
};

记住你会做some_object.once('on', function(){ console.log(this); } );

临时函数g()有self.removeListener(type,g)。我认为这是因为g()中的上下文否则会出错。但是,之后的那一行,变量this用于listener.apply(this, arguments);但是...不是这样,然后将全局上下文传递给listener(arguments)?

然后稍微向下,如果self.on,它会运行this.on

现在......我很困惑。我对Javascript很新,我仍然对上下文感到困惑。但是,这段代码驱使我香蕉......有人可以在这里赐教我吗?

谢谢,

Merc的。

1 个答案:

答案 0 :(得分:1)

在您的示例中使用this的{​​{1}}副本的原因是,在给定的函数调用中,self不会像您想要的那样设置,您可以引用已保存的复制到this并始终可以访问它。

在Javascript中,self由调用上下文设置,除非使用this.call()明确设置。

正常的函数调用将导致.apply()设置为全局对象。

this之类的方法调用会导致x.once()方法中的this设置为对象once()

在您的特定情况下,x被用作回调函数。因此,g()将由该回调函数的调用者中使用的上下文设置。但是,如果该上下文不符合要求并且this想要访问g()对象,那么它可以使用EventEmitter引用保存在self的闭包中g() 1}}驻留。如果self中没有保存的引用,则函数g()可能无法访问所需的值,因为this函数中的g()可能设置为某个值其他

如果我遵循此.once()方法的意图,那么我认为self引用没有理由,因为.on()会导致this根据需要设置g()致电this。在这种情况下,当使用没有根据需要设置self.on()的回调时,它可能只是一个遵循的约定,它可以安全地工作(即使在这个特定的代码中并非严格的情况)。 / p>

至于调用this.on()而不是this,执行没有区别。 this的值在给定的函数上下文中不会更改。有些库将this分配给局部变量然后引用局部变量主要是因为它可以在最小化时节省几个字节,因为局部变量可以由最小化器重命名为单个字节值,但值{{1}}无法重命名。

以下是一篇较长讨论的相关文章:What is the value of var me = this;