LouieLiu

关于Module.exports与exports

​ 在Node.js中require 是用来加载代码的 与之相对的exports和module.exports是用来导出代码的 每一个Node执行文件都会自动创建一个module对象 我们需要知道

  • module对象会创建一个叫exports的属性并 初始化为{}
  • exports是指向module.exports的引用
  • require() 返回的是module.exports

用一个简单的例子来类比module.exports与exports的关系:

1
2
3
4
5
6
7
8
9
10
11
12
var foo = {num:1};
var bar = foo;
console.log(foo);
console.log(bar);
bar.num = 2;
console.log(foo);
console.log(bar);
bar = {num:3};
console.log(foo);
console.log(bar);

运行结果:

1
2
3
4
5
6
Object {num: 1}
Object {num: 1}
Object {num: 2}
Object {num: 2}
Object {num: 2}
Object {num: 3}

很容易理解foo是一个对象 bar是指向foo的引用 foo和bar指向同一块内存 所以当bar改变时即内存中的内容发生改变 所以foo也随之改变 随后改变bar的指向bar开始指向另一块内存所以当bar再次改变时 foo就不会改变 所以最终结果不同 与之相对的 另一个例子:

foo.js

1
2
3
4
5
exports.foo = function(){
console.log(1);
}
exports.foo = 2;

bar.js

1
2
var bar = require('./foo');
console.log(bar.foo)

运行bar.js 结果如下:

1
2

改变foo.js 如下:

1
2
3
4
5
6
exports.foo = function(){
console.log(1);
}
module.exports = {foo:3};
exports.foo = 2;

再次运行bar.js 结果如下:

1
3

到这里 我们可以很清楚的看到 exports是指向module.exports的引用 在module.exports被改变时exports没变 require() 返回的是module.exports 所以真正执行的是module.exports 所以在bar.js中输出的是3

经常可以看到如下的使用方法:

1
exports = module.exports = somethings

它等价于:

1
2
module.exports = someting;
exports = module.exports;

即当module.exports的指向发生改变后 exports会断开与module.exports的引用 让exports=module.exports 可以让exports重新绑定module.exports

另外 module.exports 可以导出整个对象 在外部模块调用时 不能调用对象的私有方法 即prototype创建的方法不能被调用 例如:

foo.js

1
2
3
4
5
6
7
8
9
10
11
12
function foo(){
console.log("foo");
}
foo.prototype.a = function(){
console.log('a');
}
foo.b = function(){
console.log('b');
}
module.exports = foo;

bar.js

1
2
3
4
5
var bar = require('./foo');
console.log(bar);
console.log(bar.a);
console.log(bar.b);
bar.b();

结果如下:

1
2
3
4
{[Function: foo] b: [Function]}
undefined
[Function]
b