Node.js奇怪的原型inheritance

我一直通过Manuel Teixiera来跟踪Node.js ,而我在通过Event Emitter章节时偶然发现了这个奇怪的行为。

作者build议的代码包含如下内容:

var EventEmitter = require("events").EventEmitter; var util = require ("util"); var MyClass = function() {}; util.inherits(MyClass, EventEmitter); var instance = new MyClass(); instance.on("custom", function() { console.log("Holo"); }); instance.emit("custom");*/ 

哪个输出“霍洛”就好。 但是,我也阅读了关于如何使用new Function();文档和SO问题 new Function(); 是一种反面模式,面对JavaScript的原型inheritance使用。 David Walsh的这篇文章阐明了在js上强制经典inheritance和使用其原型inheritance的function之间的区别。

所以,我试图通过重写它来修改我的代码:

 var EventEmitter = require("events").EventEmitter; var clock = {}; util.inherits(clock, EventEmitter); clock.on("custom", function(){ console.log("Holo"); }); clock.emit("custom"); 

我得到一个错误,说TypeError: Object object has no method 'on' 。 我不明白这是为什么,因为我已经创build了util.inherit()帮手的时钟对象。 使用var clock = Object.create(EventEmitter)的相同的代码也不起作用。

我能得到的代码工作的唯一的例子是这样的:

 var EventEmitter = require("events").EventEmitter; var util = require("util"); var clock = {}; util.inherits(clock, EventEmitter); clock.prototype.on("custom", function(){ console.log("Holo"); }); clock.emit = function(){ clock.prototype.emit("custom"); } clock.emit(); 

这输出“霍洛”就好了。 事情是,我不明白为什么我需要访问原型来设置事件监听器或发出一个事件时,据说,我做了clockvariables委托它的方法的EventEmitter对象,所以他们应该工作正常,没有原型符号。

你能帮我吗?

根据node.js文档 :

util.inherits(constructor, superConstructor)

将原型方法从一个构造函数inheritance到另一个构造函数。 构造函数的原型将被设置为由superConstructor创build的新对象。

你正在传递一个util.inherits被devise为期望构造函数的对象。 util.inherits通过重新定义构造函数的prototype属性进行操作,该属性对构造函数构造的实例具有原型链影响。 而不是一个构造函数,你已经传入了一个对象,它的prototype属性被改变了。 这对anyting没有任何意义:你刚才在名为“ prototype ”的对象上创build了一个属性,就像你在一个名为foobar的对象上创build了一个属性一样。

有一种思想学派避免使用new (赞成调用Object.create的工厂函数 – 请参阅关于JavaScript的“新”关键字被认为是有害的讨论? ),但显然实现util.inherits的APIdevise者不分享这个观点。

然而,你尝试的Object.create(EventEmitter)确实是不正确的,因为Object.create需要一个原型对象,而不是一个构造函数。 相反,你会做Object.create(EventEmitter.prototype) 。 这与调用new EventEmitter() ,只是Object.create变体不调用EventEmitter构造函数。

我不知道Nodeinheritance的实现,但是我想它只是简单地将成员添加到第二个操作数的原型中。 因此,它假设它将通过一个构造函数。 但传递一个空对象不会抛出exception。

你将需要传递一个构造函数,并用new来调用它。 这是正常的,绝对没问题。

另外,你从哪里得到这样的想法,即使用新的和原型是互不相容的,或者说新的是要避免的? 这听起来像你可能想要更多地练习JavaScript OOP。