在node.js中require module常见的有以下几种模式
- 将exports设置为函数
foo.js
module.exports = function() {}
app.js
var foo = require('./foo');
foo();
- 给exports添加函数
foo.js
module.exports.foo = function() {}
app.js
var foo = require('./foo').foo;
foo();
- 利用构造函数将exports设置为新的对象
foo.js
function Foo() {
this.prop = 'hello world';
this.bar = function() {
console.log(this.prop);
}
}
module.exports = new Foo();
app.js
var foo = require('./foo');
foo.bar(); // hello world
利用这种方式引入module的时候会通过Foo这个构造函数生产一个新的对象并返回,我们知道new关键字会生成一个新的object,那么如果连续再调用一次就应该得到一个新的对象。答案真的是这样的么?看下面的例子:
foo.js
var foo = require('./foo');
foo.bar(); // hello world
foo.prop = 'hello world again';
app.js
var foo2 = require('./foo');
foo2.bar(); // hello world again
通过上面的例子我们可以看到,连续require两次竟然没有生成新对象,难道new关键字失效了? js语法科不是这样说的啊。其实new没有出问题,只是node.js的require函数引入module的时候会cache。也就是说第一次require的时候会读取文件中的js并执行引入文件中的js。执行完成后会把生成的对象缓存起来。这样第二次调用的时候就直接返回前面生成的对象。如果你在require这一行代码前面打一个断点,debug运行的时候点”step into”, 进入到require函数内部, 一步步调试下去,你会看到如下代码:
(如果要调试的话推荐使用webstorm或者VS,具体使用方法比较简单,不会的话google一下就明白了)
var cachedModule = Module._cache[filename];
if (cachedModule) {
return cachedModule.exports;
}
可以看到,node.js在require的时候会先从_cache取缓存对象,_cache的key就是文件名,以前引入过该文件,那么缓存中就已经存在对象,这样就直接返回缓存的对象。继续往下调试,你会看到下面两行代码:
var module = new Module(filename, parent);
Module._cache[filename] = module;
也就是说第一次引入module文件的时候会new一个Module对象并缓存起来。
- 返回构造函数
foo.js
function Foo() {
this.prop = 'hello world';
this.bar = function() {
console.log(this.prop);
}
}
module.exports = Foo;
app.js
var Foo = require('./foo');
var foo = new Foo();
foo.bar(); // hello world
- revealing module 模式
foo.js
var prop = 'hello world';
function foo() {
console.log(prop);
}
module.exports = {
foo: foo
}
app.js
var foo = require('./foo').foo;
foo(); // hello world
这种方式最吸引人的地方就在于只向外部暴露部分方法,并隐藏希望受保护的属性、方法。这有点像面向对象语言中的、protected/private。
如需转载请保留原文链接: http://www.qinyejun.com/node-js/node-js-require-module-patterns/