0

我正在查看 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);But... 这不是然后将全局上下文传递给listener(arguments)?

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

现在......我很困惑。我对 Javascript 还很陌生,但我仍然对上下文感到困惑。但是,这段代码让我发疯了……有人可以请教我吗?

谢谢,

默克。

4

1 回答 1

1

在您的示例中使用thislike副本的原因是,当在给定的函数调用中不会像您想要的那样设置时,您可以引用保存的副本并始终可以访问它。selfthisself

在 Javascript 中,除非使用orthis明确设置,否则由调用上下文设置。 .call().apply()

正常的函数调用将导致this设置为全局对象。

类似的方法调用x.once()将导致方法中设置为对象。thisonce()x

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

如果我遵循此方法的意图,那么我看不到引用的.once()理由,因为在调用. 在这种情况下,它可能只是一个正在遵循的约定,当使用未按需要设置的回调时安全工作(即使在此特定代码中严格来说并非如此)。self.on()thisg()this

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

这是一个相关的帖子,讨论时间更长:什么是 var me = this; 的价值?

于 2012-05-20T04:49:38.137 回答