exports 与 module.exports

对于使用过Node.js的同学应该对于exports 与 module.exports都很熟悉吧,那么他们之间又有什么关系呢?

exports 与 module.exports的关系

经常使用Node.js的朋友会发现,我们导出模块经常使用:

1
2
3
function a(){
}
module.exports = a;

当然,在有些地方你甚至会发现:

1
2
3
function a(){
}
module.exports = exports = a;

这时候,你会觉得奇怪,exports是什么。查nodejs你会发现,exports是module.exports的引用,所以下面的做法是错误的:

1
2
3
function a(){
}
exports = a;

根据我们对对象的了解,这样做其实就切断了exports和module.exports的联系,直接重新设置exports为函数a的引用了,而module.exports保持着原来的引用,而我们的require引用模块读取的也是module.exports的值,所以无法读取到a的函数功能。所以就有了module.exports = exports的写法,保证module.exports与exports的联系不断开。

exports的使用

那么exports如何正确的使用呢,其实这个跟原型的引用很像,我们都知道当我们需要给原型增加功能的时候,我们会使用下面的写法:

1
2
3
4
5
function a (){
}
a.prototype.test = function(){
//code
}

但如果你使用下面的写法的话,你就会切断与原型对象的联系:

1
2
3
4
5
function a (){
}
a.prototype = {
test : test
}

同理,我们这样正确使用exports对象:

1
2
3
4
5
6
7
8
9
//a.js
function a (){
console.log('blabla');
}
exports.a = a;

//b.js
var a = require(./a.js);
a.a();//blabla

同理于sea.js

我们都知道,sea.js是使用return或者是nodejs导出方法进行模块导出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//method1
define(function(require, exports) {

// 对外提供 foo 属性
exports.foo = 'bar';
// 对外提供 doSomething 方法
exports.doSomething = function() {};
});

//method2
define(function(require) {

// 通过 return 直接提供接口
return {
foo: 'bar',
doSomething: function() {}
};

});

但如果使用下面的写法的话就是错误的:

1
2
3
4
5
6
7
8
9
define(function(require, exports) {

// 错误用法!!!
exports = {
foo: 'bar',
doSomething: function() {}
};

});

同样要使用下面的写法才是正确的:

1
2
3
4
5
6
7
8
9
define(function(require, exports, module) {

// 正确写法
module.exports = {
foo: 'bar',
doSomething: function() {}
};

});