javascript - Node.js 奇怪的原型(prototype)继承

标签 javascript node.js inheritance prototypal-inheritance

我一直在关注 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/

相关文章:

node.js - 如何为 @PrimaryColumn() 设置 AUTO_INCRMENT?

javascript - 在 Node JS/Express Web 应用程序中生成 PDF 报告

javascript - 如何使用 Underscore.js 从平面列表创建嵌套对象?

javascript - 通过 JavaScript 更改 body 标签样式

javascript - Javascript 函数怎么可能未定义但仍然可以调用?

node.js - 如何在保存之前检查该数据是否已存在于数据库中

android - 以编程方式创建 FloatingActionButton(无 xml)

c# - 调用二级基类构造函数

c++ - 如果仅存在私有(private)函数,则访问基类中的私有(private)数据类型

javascript - React hooks 状态变量在重新渲染后未更新