尽管用函数和变量组装exports对象能满足大多数的模块创建需要,但有时你可能需要用不同的模型创建该模块。
比如说,前面创建的那个货币转换器模块可以改成只返回一个Currency构造函数,而不是包含两个函数的对象。
一个面向对象的实现看起来可能像下面这样:
const Currency = require('./currency');
const canadianDollar = 0.91;
const currency = new Currency(canadianDollar);
console.log(currency.canadianToUS(50));
如果只需要从模块中得到一个函数,那从 require 中返回一个函数的代码要比返回一个对象的代码更优雅。
要创建只返回一个变量或函数的模块,你可能会以为只要把 exports设定成你想返回的东西就行。
但其实这样是不行的,因为Node觉得不能用任何其他对象、函数或变量给exports赋值。
举个栗子:【一个不能用的模块】
class Currency{
constructor(canadianDollar){
this.canadianDollar = canadianDollar;
}
roundTwoDecimals(amount){
return Math.round(amount * 100) / 100;
}
canadianToUS(canadian){
return this.roundTwoDecimals(canadian * this.canadianDollar);
}
USToCanadian(us){
return this.roundTwoDecimals(us / this.canadianDollar);
}
}
exports = Currency;
为了让这个模块可以使用,需要把 exports换成 module.exports。
用module.exports 可以对外提供单个变量、函数或者对象。
!注意:如果你创建了一个既有exports 又有 module.exports 的模块,那它只会返回module.exports,而exports 会被忽略。
这次再执行:
成功了。
【一个思考】“导出的到底是什么?”
最终在程序里导出的是module. exports。exports 只是对module.exports的一个全局引用,最初被定义为一个可以添加属性的空对象。exports.myFunc只是module.exports.myFunc的简写。
所以,如果把 exports设定为别的,就打破了module.exports和exports之间的引用关系。可是因为真正导出的是module.exports,那样exports就不能用了,因为它不再指向module.exports了。如果你想保留那个链接,可以像下面这样让module.exports再次引用exports:
module.exports = exports = Currency;
- 1
根据需要使用exports 或 module.exports 可以将功能组织成模块,规避掉程序脚本一直增长所带来的弊端。