如何“子类化”一个node.js模块

我多年来一直是Perl编程人员,但也有C ++的背景,所以我来自“经典”面向对象的背景,现在正在学习node.js。 我刚刚阅读了“面向对象的JavaScript原则” ,它很好地向像我这样有经典头脑的人解释面向对象的JS概念。 但我留下了一个问题,具体涉及到node.js和inheritance。 如果我还在用“古典”词汇来解释我的问题,请原谅我。

让我们假设我有一个模块lib/foo.js

 function foo() { console.log('Foo was called'); } module.exports.foo = foo; 

我想在另一个模块lib/bar.js ”这个:

 var foo = require('foo.js'); // Do some magic here with *.prototype, maybe? function bar() { console.log('Bar was called'); } module.exports.bar = bar; 

这样我的主要脚本可以做到这一点:

 var bar = require('lib/bar.js'); bar.foo(); // Output "Foo was called" bar.bar(); // Output "Bar was called" 

这甚至有可能吗? 如果是这样,我错过了什么?

或者这是一种反模式? 或者根本不可能? 我该怎么做呢?

以下是我如何做到的,以覆盖请求模块中的一个方法。 警告 :许多节点模块的扩展devise很差,包括请求,因为它们在构造函数中做太多东西。 不只是一个巨大的参数选项,而是启动IO,连接等。例如,请求将http连接(最终) 作为构造函数的一部分 。 没有明确的.goDoIt().goDoIt()方法。

在我的例子中,我想使用querystring而不是qs格式化表单。 我的模块巧妙地命名为“MyRequest”。 在名为myrequest.js的单独文件中,您有:

 var Request = require('request/request.js'); var querystring = require('querystring'); MyRequest.prototype = Object.create(Request.prototype); MyRequest.prototype.constructor = MyRequest; // jury rig the constructor to do "just enough". Don't parse all the gazillion options // In my case, all I wanted to patch was for a POST request function MyRequest(options, callbackfn) { "use strict"; if (callbackfn) options.callback = callbackfn; options.method = options.method || 'POST'; // used currently only for posts Request.prototype.constructor.call(this, options); // ^^^ this will trigger everything, including the actual http request (icky) // so at this point you can't change anything more } // override form method to use querystring to do the stringify MyRequest.prototype.form = function (form) { "use strict"; if (form) { this.setHeader('content-type', 'application/x-www-form-urlencoded; charset=utf-8'); this.body = querystring.stringify(form).toString('utf8'); // note that this.body and this.setHeader are fields/methods inherited from Request, not added in MyRequest. return this; } else return Request.prototype.form.apply(this, arguments); }; 

然后,在你的应用程序中,而不是

 var Request = require("request"); Request(url, function(err, resp, body) { // do something here }); 

你走

 var MyRequest = require("lib/myrequest"); MyRequest(url, function(err, resp, body) { // do that same something here }); 

我不是一个JavaScript大师,所以可能有更好的方法…

作为参考,我提出了我的示例代码问题的具体解决scheme如下:

lib/foo.js

 var Foo = function() {} Foo.prototype.foo = function() { console.log('Foo was called!'); }; module.exports = new Foo; 

lib/bar.js

 var foo = require('./foo.js'); var Bar = function() {} Bar.prototype = Object.create(foo.__proto__); Bar.prototype.constructor = Foo; Bar.prototype.bar = function() { console.log('Bar was called!'); }; module.exports = new Bar; 

然后在我的testing脚本中:

 var bar = require('lib/bar.js'); bar.foo(); // Output "Foo was called" bar.bar(); // Output "Bar was called"