【发布时间】:2015-04-19 02:39:35
【问题描述】:
我非常喜欢将函数导出为 JavaScript 模块的主要 API 的模式。原因是在 JS 中,一个函数基本上可以做任何典型对象可以做的事情,然后再做一些。
所以这对我来说很典型:
function stuff() {}
function thing() { /* shortcut or default behavior */ }
thing.stuff = stuff;
module.exports = thing;
现在我遇到了一种情况,我希望thing 的行为类似于EventEmitter 的实例。而且我不希望它成为构造函数。
为什么?好吧,thing 确实与osPreferences 类似,使用一些选项调用它会将数据保存到磁盘。用户实例化它没有任何意义。 new OSPreferences() 没有多大用处,因为您的计算机一次只能尊重一组偏好。
然而,更改可以随时发生,在我的 API 之外。所以有一个巨大的好处:
osPreferences.on('change', fn);
所以问题是,什么是吸收 EventEmitter instance 行为的可靠模式?简单地遍历一次性实例的所有属性并将它们复制到目标函数是否足够好?是否值得尝试模仿继承与非继承的设置?考虑到默认的this 将被更改,是否有任何奇怪的情况需要考虑?或者有没有更好、更明智的方法?
【问题讨论】:
-
你可以扩展节点的事件发射器,不需要重新发明轮子。
-
我见过的每一段“扩展”EventEmitter 的代码都被实现为一个构造函数,调用 EventEmitter 作为一个超构造函数。还是您指的是
_.extend(fn, (new EventEmitter()))之类的东西?后者让我觉得很奇怪,所以我问它是否有任何设计缺陷。 -
我通常只添加自己的属性来在新的 EE 上创建方法,因为我不需要继承,因为通常由一个 EE 处理这项工作。通常,它只不过是在我关闭模块之前添加一两个新方法并调用一些 this.on() 来设置一些行为
-
如果我想导出一个简单的对象,给它分配一个新的 EE 并添加方法会很简单,同意。但在这种情况下,我想要实现的是一个函数来代替那个新的 EE 对象。因此,似乎我别无选择,只能从一次性的新 EE 中手动复制所有内容,如果我做出太多假设,这势必容易出错或出错。
-
我不明白为什么容器需要是一个函数,但是 fn.ee=myEE;工作,还是方法需要是函数本身的属性?如果是这样,请使用 extend()...
标签: javascript node.js eventemitter