为什么需要模块系统?

在Node.js中,我们可以将代码拆分成多个独立的文件,每个文件就是一个“模块”。这样做的好处是:
- 代码复用:不同文件可以共享功能(比如工具函数、配置信息)。
- 代码组织:将不同功能的代码放在不同文件中,便于维护和查找。
- 避免全局污染:模块内的变量和函数默认只在模块内部可见,不会影响其他文件。

一、Node.js中的模块是什么?

每个.js文件都是一个独立的模块。例如,新建一个utils.js文件,它就是一个模块。模块内部的变量、函数、类等默认是“私有的”,只有通过导出机制才能被外部模块访问。

二、如何导出模块内容(exports)?

要让其他模块使用当前模块的内容,需要通过exports对象导出。exports是一个默认空的对象,我们可以向其中挂载属性或方法。

1. 导出单个值

// utils.js
exports.PI = 3.14159; // 导出一个常量
exports.add = (a, b) => a + b; // 导出一个函数

2. 导出多个值

如果需要导出多个属性或方法,可以直接给exports对象添加多个属性:

// utils.js
exports.name = "Node.js";
exports.version = "18.0.0";

exports.log = (msg) => console.log("日志:", msg);

3. 导出整个对象

如果需要导出一个复杂对象(如配置、类等),可以直接将对象赋值给exports

// config.js
const config = {
  port: 3000,
  db: "mysql",
  secret: "abc123"
};

module.exports = config; // 直接导出对象(注意:也可用 exports = config,但更推荐 module.exports)

三、如何导入模块内容(require)?

要使用其他模块的内容,使用require函数导入模块。require会返回被导入模块的导出内容。

1. 导入本地模块

导入当前项目中的模块时,需要使用相对路径(以./../开头):

// main.js
const utils = require("./utils.js"); // 导入当前目录下的 utils.js
const config = require("./config.js"); // 导入当前目录下的 config.js

// 使用导出的内容
console.log(utils.PI); // 3.14159
console.log(utils.add(1, 2)); // 3
console.log(config.port); // 3000

2. 导入第三方模块

如果是导入Node.js包(如expresslodash),直接写包名即可:

const express = require("express"); // 导入 express 模块
const _ = require("lodash"); // 导入 lodash 模块

四、关键细节:exports与module.exports的关系

  • exportsmodule.exports引用(即exports = module.exports),默认指向一个空对象。
  • 我们可以通过exports直接挂载属性(如exports.xxx = ...),或直接给module.exports赋值(如module.exports = { ... })。
  • 注意:如果直接给exports赋值(如exports = { a: 1 }),可能会覆盖默认的module.exports,因此更推荐通过exports.xxxmodule.exports导出。

五、综合示例

假设我们有两个文件:math.js(导出数学工具)和main.js(导入并使用)。

1. 导出模块(math.js)

// math.js
exports.add = (a, b) => a + b;
exports.subtract = (a, b) => a - b;
exports.multiply = (a, b) => a * b;

2. 导入模块(main.js)

// main.js
// 导入 math.js 模块
const math = require("./math.js");

// 使用导出的函数
console.log("1+2=", math.add(1, 2)); // 输出:1+2=3
console.log("5-3=", math.subtract(5, 3)); // 输出:5-3=2
console.log("2*4=", math.multiply(2, 4)); // 输出:2*4=8

3. 运行结果

在终端执行node main.js,即可看到输出结果。

总结

  • 模块:每个.js文件是一个模块,内部内容默认私有。
  • 导出:通过exportsmodule.exports将内容暴露给外部。
  • 导入:通过require引入其他模块,使用其导出的内容。

掌握exportsrequire是Node.js开发的基础,后续学习框架(如Express)和工具库(如Webpack)时会频繁用到。多练习不同模块的导出与导入,能快速提升代码组织能力!

小夜