我正在尝试将解释here的模块扩充JavaScript模式应用于控制台node.js应用程序。
首先我有文件get-set.js
,它实现了一个只有get
和set
方法的简单模块:
var module = (function() {
var x = 0;
function get() {return x;}
function set(_x) {x = _x;}
return {
get: get,
set: set};
})();
module.set(10);
console.log(module.get());
以上代码有效。
现在,我正在尝试按照模式中的下一步并在单独的文件get-set-inc.js
中找到一些额外的功能(比如增加计数器的方法):
require('./get-set.js');
var module = (function(m) {
function inc() {m.set(m.get()+1);}
m.inc = inc;
return m;
})(module);
module.inc();
console.log(module.get());
不幸的是,当我在node.js下运行后一个文件时,我没有成功扩充模块。事实上我得到了:
$ ls
get-set-inc.js get-set.js
$
$ node get-set-inc.js
10
[...]/get-set-inc.js:4
function inc() {m.set(m.get()+1);}
^
TypeError: Object #<Module> has no method 'get'
at Module.inc ([...]/get-set-inc.js:4:33)
at Object.<anonymous> ([...]/get-set-inc.js:9:12)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:929:3
经过进一步检查,我逐渐意识到问题在于使用require
。那么我应该如何在node
应用程序中加载外部JavaScript文件,以便我可以按照上面链接中讨论的各种增强模式进行操作?
答案 0 :(得分:2)
首先是代码,然后是下面的一些注释。
module.exports = function gsFactory() {
var x = 0;
function get() {
return x;
}
function set(_x) {
x = _x;
}
return {
get: get,
set: set
};
}
//prints 0
console.log(module.exports().get());
var gs = require('./get-set');
module.exports = function gsiFactory() {
var instance = gs();
function inc() {
instance.set(instance.get()+1);
}
instance.inc = inc;
return instance;
};
// demo
var gsi = module.exports();
gsi.inc();
// this prints 1
console.log(gsi.get());
gsi.inc();
// this prints 2
console.log(gsi.get());
node get-set-inc.js
0
1
2
这就是我打算建立的东西。一个问题是module
是由包装函数在node.js中预定义的,所以不要使用&#34; module&#34;作为一个变量名,因为你会破坏CommonJS&#34;模块&#34;名称意味着您无法正确导出您的API。
通常在节点中,所有CommonJS模块都自动包装在一个函数中,因此不需要包含IIFE包装器代码。 wrapper code看起来像这样:
NativeModule.wrapper = [
'(function (exports, require, module, __filename, __dirname) { ',
'\n});'
];
要导出工厂函数(这是我对此模式的看法),只需将module.exports
指定为该函数即可。这在节点中非常常见(表达了这种情况,许多连接中间件模块等)。
上面的方法并没有使用构造函数或原型。它可能更容易理解,但它的缺点是每次都定义新的get
,set
和inc
方法。如果导出的构造函数访问原型上只定义一次的方法,则所有实例都可以共享这些方法。一点微优化,但了解如何以两种方式编码是很好的。