如何在NodeJS中扩展对象文字对象以用于事件?

9
我正在尝试让我的Node.js对象“投射事件”。 如果我制作“静态”对象并实例化它们,这不是问题,但是当我的对象没有静态祖先时,例如使用“对象字面量”符号创建对象时,我该怎么办?
我习惯编写ExtJS语法,因此更喜欢一切都在对象字面量中。
// var EventEmitter = require('events').EventEmitter; // How where when?

myObject = {
  myFunction: function() {
    console.log('foo');
  },
  urFunction: function() {
    console.log('bar');
  }
};

这是一个对象。它没有构造函数,因为不需要更多的实例。

现在我该如何让myObject发出事件呢?

我尝试了很多次去调整代码,但如果不将我的对象改写成具有构造函数的形式,我无法使其正常工作,像这样:

var EventEmitter = require('events').EventEmitter;
var util = require('util');

function myClass() {
  EventEmitter.call(this);

  myFunction: function() {
    this.emit('foo');
  },
  urFunction: function() {
    this.emit('bar');
  }
};

myClass.prototype = Object.create(EventEmitter.prototype);
// or // util.inherits(myClass, EventEmitter);
var myObject = new myClass; // Shouldn't be necessary for my single-instance case

或者将我的函数/原型添加到已构建的内容中,例如:
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var myObject = new EventEmitter();
// or // var myObject = Object.create(new EventEmitter); // Dunno difference
myObject.myFunction = function() {
    this.emit('foo');
  },
myObject.urFunction = function() {
    this.emit('bar');
  }
};

util.inherits(myObject, EventEmitter);

如何使myObject能够发出事件,同时保持对象字面符号表示法? 有很多混乱的方法可以做到这一点,但是没有一种方法适用于那些类似于JSON格式的对象。


非常好的问题,我喜欢在基于浏览器的环境中使用Object.create()和字面量,但是现在已经使用node js一段时间了,我的结论是ES5类似的对象处理方式有些被低估了。原因可能是像util.inherits这样的函数不存在于处理对象字面量中。 - vanthome
请查看此答案: http://stackoverflow.com/questions/24925115/how-to-add-event-ability-to-object-instance-in-node/24934255#24934255 - victorwoo
3个回答

9
为什么不使用组合而不是继承?
var myObject = {
  myFunction: function() {
    console.log('foo');
  },
  urFunction: function() {
    console.log('bar');
  },
  emitter: new EventEmitter()
}

这看起来很有趣。当myObject作为emitter时,“internal” emitter是否与“public”一样?例如,我可以从根函数中执行self.myObject.emitter.on('customEvent', doSomethinG());(前提是在同一根中设置了self = this)? - Redsandro
2
是的。如果你想让你的对象像发射器一样“quack”,你甚至可以添加一些你将使用的发射器函数,比如 var myObject = { ... emitter: new EventEmitter(), emit: myObject.emitter.emit, on: myObject.emitter.on, ...} - ziad-saab
聪明。只是好奇这个多功能性有多强:我是否可以以某种方式从单独的函数/作用域传递发射器并拥有相同的乐趣?例如,一个_nodejs请求_触发onRequest(),它对myObject执行某些操作,导致事件被监听在onRequest()内部。现在,第二(第三和_n_th)同时请求做同样的事情,但应该仅侦听由其自己与myObject搞弄引起的事件。这将要求onRequest()每次都向myObject传递一个新的发射器,否则myObject的事件将被每个运行中的onRequest()实例捕获。 - Redsandro
我不确定我100%理解你的最后一个问题。但是请看这个方面:你继承了所有“EventEmitter”的功能。但是,你不是通过扩展EventEmitter来继承它们,而是通过将EventEmitter作为对象的一部分来继承它们。 - ziad-saab

8

很遗憾,您想要的对象字面量语法不可能实现。这是因为

var obj = {};

等同于

var obj = Object.create(Object.prototype);

在创建时,obj的原型固定为Object.prototype,后续无法更改。

既然您只需要一个单独的实例,我认为创建EventEmitter的一个实例并对其属性进行赋值是有意义的:

var EventEmitter = require('events').EventEmitter;
var obj = new EventEmitter();

obj.doStuff = function() {
  this.emit('stuff');
};

在这里你不需要使用util.inherits,因为你只有一个实例,所以没有需要设置的链。


感谢您解释了“prototype”的部分。我只是部分地理解了发生了什么,并认为{}是定义和实例化无构造函数对象的速记方式。您知道一种更本地的方法来分配属性给“EventEmitter”实例,以便我可以更轻松地将我的“对象文字”移植到它们中,正如我在对Mattias Buelens的第一条评论中所引用的那样吗? - Redsandro
1
我不知道有一种本地的方法可以通过对象字面量进行扩展。然而,包含jQuery并不是node.js项目的理想选择,因为大多数jQuery都是关于操作DOM的。我建议包含一个实用程序库,如Lo-DashUnderscore。你可以使用npm安装它。 - J. Ryan Stinnett
非常好的解释,但如果您创建一个可重用的库,您提出的解决方案是不明智的。在这种情况下,您将不希望在构建之后添加功能。 - vanthome
如果jQuery有这个东西,你不是可以尝试从jQuery js文件中找到相关部分,然后只复制那些部分吗? - Julix

-1

这只是一个猜测,因为我只在浏览器中编写过JavaScript。但是,在创建对象文字之后,您无法在对象上调用EventEmitter吗?

myObject = {
    myFunction: function() {
        console.log('foo');
    },
    urFunction: function() {
        console.log('bar');
    }
};
EventEmitter.call(myObject);

我希望它是那么简单,但不幸的是它不起作用。模仿将我的“对象文字”转换为“事件发射器”的一种肮脏方法是通过借用jQuery的extend()来实现:var myObject = new EventEmitter(); $.extend(myClass, myObject);其中myClass是我的“对象文字”。显然,我正在寻找一种更本机的方法。 - Redsandro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接