命名导出和默认导出
exports
对象支持两种导出方式:命名导出和默认导出。命名导出允许我们通过特定名称导出模块中的变量、函数或类等值,而默认导出则只能导出一个值,并且在导入模块时不需要指定名称。
// 命名导出
exports.myFunction = function() { ... };
exports.myVariable = 10;
// 默认导出
exports.default = MyDefaultClass;
模块包装器函数
为了避免与其他模块的全局变量冲突,Node.js 使用了一个模块包装器函数。该函数接收两个参数:require
函数和一个工厂函数。工厂函数负责创建模块的实际内容,并将其导出到 module.exports
对象。
(function(require, module, exports) {
// 模块代码
exports.myFunction = ...;
})(require, module, exports);
惰性求值
在模块包装器函数中使用惰性求值技术可以延迟模块的计算,直到其被实际需要时才进行。这对于涉及昂贵或耗时的操作的模块非常有用。
(function() {
var myCache;
exports.getCachedValue = function() {
if (!myCache) {
// 计算并缓存值
myCache = ...;
}
return myCache;
};
})();
循环依赖
当两个或多个模块互相依赖时,可能会出现循环依赖的问题。为了解决这个问题,Node.js 允许模块在导出自身之前先引用其他模块。
// 模块 A
exports.B = require("./B");
// 模块 B
exports.A = require("./A");
导出动态值
exports
对象允许我们导出动态计算的值。这对于创建根据模块内部状态而变化的模块非常有用。
exports.getValue = function() {
// 基于模块内部状态计算值
return ...;
};
修改导出对象
在模块内,我们可以使用 module.exports
而不是 exports
来访问 exports
对象。这允许我们修改 exports
对象,从而定制导出的内容。
module.exports = {
// 原始导出
...exports,
// 额外的导出
myNewFunction: ...
};
小结
通过理解这些进阶技巧,我们可以更有效地使用 Node.js 的 exports
对象进行模块化开发。命名导出、默认导出、模块包装器函数、惰性求值、循环依赖、导出动态值和修改导出对象等技术可以帮助我们创建更灵活、更可扩展的模块。