Nodejs中的exports 和 module.exports

译自http://www.hacksparrow.com/node-js-exports-vs-module-exports.html

Nodejs中的exports和module.exports有什么区别?

你肯定对nodejs中的exports概念有所了解,如下在nodejs的模块中创建函数(假设有个rock.js的文件)

exports.name = function() {
    console.log('My name is Lemmy Kilmister');
};

在其他文件中这样引入并使用:

var rocker = require('./rocker.js');
rocker.name(); // 'My name is Lemmy Kilmister'

module.exports究竟是什么?甚至它是否合法呢?
令人大开眼界的是module.exports才是真实引用,exports不过是其一个辅助。
模块真正返回的是module.exports的引用给调用者,而非exports。
exports所做的是收集属性并绑定到module.exports。前提是module.exports对象上未有绑定。
如果module.exports已有绑定,exports的收集则被忽略。

添加如下代码到rock.js:

module.exports = 'ROCK IT!';
exports.name = function() {
    console.log('My name is Lemmy Kilmister');
};

引用时:

var rocker = require('./rocker.js');
rocker.name(); // TypeError: Object ROCK IT! has no method 'name'

rocker模块忽略exports.name并返回一个字符串‘ROCK IT’,你或许发现模块并不一定非得返回一个实例化的模块,
可以是任意的javascript数据类型。你的模块返回是任意设置给module.exports的值。
如果没有设置module.exports,则使用exports给module.exports绑定属性、方法。

下面的例子,模块是一个类:

module.exports = function(name, age) {
    this.name = name;
    this.age = age;
    this.about = function() {
        console.log(this.name +' is '+ this.age +' years old');
    };
};

这样去使用:

var Rocker = require('./rocker.js');
var r = new Rocker('Ozzy', 62);
r.about(); // Ozzy is 62 years old

你的模块还可以是一个数组:

module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];

使用:

var rocker = require('./rocker.js');
console.log('Rockin in heaven: ' + rocker[2]); //Rockin in heaven: Ronnie James Dio

如果你想你的模块是特定类型,你可以使用module.exports。如果你想你的模块是个实例化的对象,可以使用exports

给moduels.exports添加属性和exports上添加属性类似,如下:

module.exports.name = function() {
    console.log('My name is Lemmy Kilmister');
};

同理:

exports.name = function() {
    console.log('My name is Lemmy Kilmister');
};

但是两者不是一个东东。如前面所说,module.exports是最后的引用而exports只是其一个辅助。
只要你没有给module.exports作赋值操作。在require操作的引用模块里,module.exports和exports都可以获取到。

模块如下:

module.exports.age = 68;
exports.name = 'Lemmy Kilmister';

引用:

var rocker = require('./rocker.js');
console.log('%s is %s', rocker.name, rocker.age); // Lemmy Kilmister is 68

如果你复写了module.exports对象,那么上面的require就不能“如愿”获取。

module.exports = 'LOL';
module.exports.age = 68;
exports.name = 'Lemmy Kilmister';

或者

module.exports.age = 68;
exports.name = 'Lemmy Kilmister';
module.exports = 'WTF';

上面的例子可以看出,module.exports重新赋值的操作所在位置的不同不影响结果。
即:打印rocker.age 和 rocker.name 的值都会是 undefined。

注意: 虽然module.exports.age 和 exports.name 都会被导出,但是不建议用这种方式。
我的建议是优先使用** exports.* **。

posted @ 2017-07-11 17:31  douglasvegas  阅读(166)  评论(0编辑  收藏  举报