我一直在关注 Manuel Teixiera 的 Hands-On Node.js,并且在阅读 Event Emitter 一章时偶然发现了这种奇怪的行为。
作者建议的代码包含如下内容:
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");*/
输出“Holo”就好了。但是,我也阅读了文档和 SO questions关于如何使用 new Function();
的主题是一种反模式,它与 javascript 对原型(prototype)继承的预期用途背道而驰。 This article by David Walsh说明了在 js 上强制经典继承与使用其功能进行原型(prototype)继承之间的区别。
所以,我尝试通过重写来修改我的代码:
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'
。我不明白为什么会这样,因为我使用 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();
这会很好地输出“Holo”。问题是,我不明白为什么我需要访问原型(prototype)来设置事件监听器或发出事件,据推测,我让 clock
变量将它的方法委托(delegate)给 EventEmitter
对象,因此它们在没有原型(prototype)符号的情况下应该可以正常工作。
你能帮帮我吗?
最佳答案
根据node.js docs :
util.inherits(constructor, superConstructor)
Inherit the prototype methods from one constructor into another. The prototype of constructor will be set to a new object created from superConstructor.
您正在传递一个对象,其中 util.inherits
旨在期待一个构造函数。 util.inherits
通过重新定义构造函数的 prototype
属性进行操作,该属性对由该构造函数构造的实例具有原型(prototype)链含义。您传入了一个对象,而不是构造函数,该对象的 prototype
属性已更改。这对任何事情都没有影响:您刚刚在名为“prototype
”的对象上创建了一个属性,这与您在名为 foobar 的对象上创建了一个属性一样特别
。
有一种思想流派避免使用 new
(支持调用 Object.create
的工厂函数——参见 Is JavaScript's "new" keyword considered harmful? 上的讨论),但是显然,实现 util.inherits
的 API 设计者不同意这种观点。
但是,您尝试的 Object.create(EventEmitter)
确实不正确,因为 Object.create
需要原型(prototype)对象,而不是构造函数。相反,您会执行 Object.create(EventEmitter.prototype)
。这与调用 new EventEmitter()
相同,只是 Object.create
变体不调用 EventEmitter
构造函数。
关于javascript - Node.js 奇怪的原型(prototype)继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23616474/