2012-12-06 73 views
1

我一直在探索一些Node.js模块,希望学习在创建具有类似功能的模块时可能错过的东西。然后,我遇到了这个代码HoundNode.js中的奇怪继承

function Hound() { 
    //why this? 
    events.EventEmitter.call(this) 
} 

//ok, so inheriting the EventEmitter 
util.inherits(Hound, events.EventEmitter); 

我知道,从Node.js的的util.inherits()函数创建一个新的父实例为孩子构造as stated in the docs的原型:

构造函数的原型将被设置为由superConstructor创建的新对象。

所以,如果我们的构造是通过util.inherits()继承EventEmitter,什么是在构造函数的代码?

+0

看起来像我的坏代码 –

+0

我已经看到这种类型的事情时不时。我总是认为需要在正在构建的实例上显式调用超级构造函数。鉴于从文档摘录,但我不知道是否有必要。也许这是从'继承'工作时不同的遗留下来的旧惯例? – chesles

+0

这不是错误的代码; JavaScript没有其他语言的所有继承细节。这只是node.js期望你如何使用EventEmitter类。 –

回答

1

这只是让您的Hound类为EventEmitter对象。

它给你的EventEmitter instance methods的类。

例如,houndInstance.emit('something')正在监听这些事件则可以回应他们

其他对象。


每您的评论:

// constructor 
function Hound() { 

    // equivalent of calling a "super" or "parent" constructor 
    SomeClass.call(this); 
} 

在JavaScript中,.call(context)是在特定的情况下调用功能的一种手段。在上面的示例中,我们只是调用SomeClass构造函数并将this(本例中的Hound类)作为上下文。

+0

但是'util.inherits()'已经覆盖了那个?或者我错过了什么? – Joseph

+0

请参阅我的编辑 –

1

从您的评论:

但不util.inherits()已覆盖?或者我错过了什么?

你缺少的是util.inherits()只是继承父对象。它没有设置构造函数来自动调用父对象的构造函数。在大多数情况下,这足够了,因为大多数对象在其构造函数中没有做太多初始化。

但是events.EventEmitter显然在构造函数中做了一些初始化,有一些重要的副作用。由于原型继承不会自动调用父项的构造函数,因此在这种情况下需要手动调用它。因此,events.EventEmitter.call(this)线。


请注意,另一种方法是使用始终调用父项构造函数的模块模式。这是因为模块模式本身不是继承,而是通过滥用mixin/decorator模式来模拟继承 - 它会从父构造器创建一个对象并手动向其添加属性。许多人不喜欢模块模式,因为它重复了函数和属性 - 因此他们将其视为浪费内存。此外,这不是适当的继承,所以打破像instanceof这样的东西。