原文:module.exports – How to Export in Node.js and JavaScript,作者:Dillion Megida
在编程中,模块是一个程序的组成部分,具有一个或多个功能或值。
这些值也可以在整个程序中共享,并可以以不同的方式使用。
在这篇文章中,我将告诉你如何在 Node.js 中通过导出和导入模块来共享函数和值。
为什么要导出模块
你想导出模块,这样你就可以在你的应用程序的其他部分使用它们。
模块可以有不同的用途。它们可以提供简单的实用程序来修改字符串,可以提供 API 请求的方法,或者甚至可以提供常量和原始值。
当你导出一个模块时,你可以把它导入到你的应用程序的其他部分并使用它。
Node.js 支持 CommonJS 模块和 ECMAScript 模块。
在本文的其余部分,我们将专注于 CommonJS 模块,这是 Node.js 中打包模块的原始方法。
如果你想了解更多关于 ES 模块(以及 CommonJS 模块)的信息,你可以查看这份详细指南。
如何在 Node 中导出模块
Node.js 已经导出了内置的模块,例如 fs、path 和 http。但你也可以创建你自己的模块。
Node.js 将 Node 项目中的每个文件视为一个模块,可以从文件中导出值和功能。
例如,你有一个 utility 文件 utility.js
,代码如下:
// utility.js
const replaceStr = (str, char, replacer) => {
const regex = new RegExp(char, "g")
const replaced = str.replace(regex, replacer)
return replaced
}
utility.js
是一个模块,其他文件可以从中导入东西。但是 utility.js
目前并没有输出任何东西。
你可以通过检查每个文件中的全局 module
对象来验证这一点。当你打印这个 utility 文件中的 module
全局对象时,你有:
console.log(module)
// {
// id: ".",
// path: "...",
// exports: {},
// parent: null,
// filename: "...",
// loaded: false,
// children: [],
// paths: [
// ...
// ],
// }
module
对象有一个 exports
属性,正如你所看到的,它是一个空对象。
因此,任何试图从这个文件中导入任何东西的行为都会产生错误。
utility.js
文件有一个 replaceStr
方法,可以用一些其他字符替换字符串中的字符。我们可以从这个模块导出这个函数,供其他文件使用。
方法如下:
// utility.js
const replaceStr = (str, char, replacer) => {
const regex = new RegExp(char, "g")
const replaced = str.replace(regex, replacer)
return replaced
}
module.exports = { replaceStr }
// or
exports.replaceStr = replaceStr
现在, replaceStr
可以在应用程序的其他部分使用。要使用它,你要像这样导入它:
const { replaceStr } = require('./utility.js')
// then use the function anywhere
module.exports vs exports in Node
你可以使用 module.exports
从一个模块中导出函数和值:
module.exports = { value1, function1 }
或者使用 exports
:
exports.value1 = value1
exports.function1 = function1
区别是什么?
这些方法是相同的。基本上,exports
是对 module.exports
的引用。为了更好地理解这一点,让我们通过使用两种导出值的方式来填充 exports
对象:
const value1 = 50
exports.value1 = value1
console.log(module)
// {
// id: ".",
// path: "...",
// exports: { value1: 50 },
// parent: null,
// filename: "...",
// loaded: false,
// children: [],
// paths: [
// ...
// ],
// }
const function1 = function() {
console.log("I am a function")
}
module.exports = { function1, ...module.exports }
console.log(module)
// {
// id: ".",
// path: "...",
// exports: { function1: [Function: function1] },
// parent: null,
// filename: "...",
// loaded: false,
// children: [],
// paths: [
// ...
// ],
// }
这里有两件事需要注意:
exports
关键字是对modules
对象中exports
对象的引用。通过exports.value1 = value1
,它将value1
属性添加到module.exports
对象中,正如你在第一个日志中看到的那样。- 第二条日志不再包含
value1
的导出。它只有使用module.exports
导出的函数。为什么会这样呢?
module.exports = ...
是将一个新对象重新分配给 exports
属性的一种方式。这个新对象只包含函数,所以 value1
不再被导出。
那么有什么区别呢?
只用 exports
关键字导出数值是一种快速导出模块中数值的方法。你可以在顶部或底部使用这个关键字,它所做的只是填充 module.exports
对象。但如果你在一个文件中使用 exports
,请坚持在整个文件中使用它。
使用 module.exports
是一种明确指定模块导出的方式。在一个文件中最好只存在一次。如果它存在两次,第二次声明就会重新分配 module.exports
属性,而模块只输出第二次声明中的内容。
因此,作为前面代码的解决方案,你可以像这样导出:
// ...
exports.value1 = value1
// ...
exports.function1 = function1
或者像这样:
// ...
module.exports = { value1, function1 }
总结
Node.js 项目中的每个文件都被视为一个模块,可以导出值供其他模块使用。
module.exports
是 Node.js 文件中的一个对象,用于保存该模块导出的值和函数。
在一个文件中声明一个 module.exports
对象,指定从该文件中导出的值。导出后,另一个模块可以通过 require
全局方法导入这些值。