Node.js模块系统

写代码最怕啥?就是一个文件堆所有东西,到后面自己都看不懂了。好在Node.js有模块系统帮你撑腰!这节课我们来聊聊怎么把代码拆分成一个个小模块,让你的项目整整齐齐、易维护。

一、 为什么要用模块

想象一下,你要开发一个博客系统:

如果全塞在一个app.js里,估计有上万行,看都看不过来。拆分成独立模块后:

是不是清晰多了?

二、 两种模块类型

Node.js有两种模块:

1. 内置模块(原生模块)

Node.js自带的核心模块,直接引用就能用:

// 引入文件系统模块 const fs = require('fs');

// 引入路径模块 const path = require('path');

// 引入http模块 const http = require('http');

2. 自定义模块

你自己写的模块:

// 引入自己写的math.js const math = require('./math');

注意哈,引入自定义模块要加 "./" ,表示当前目录。

三、 module.exports 导出模块

这是最常用的方式。先创建一个 math.js 文件:

// math.js function add(a, b) { return a + b; }

function subtract(a, b) { return a - b; }

function multiply(a, b) { return a * b; }

function divide(a, b) { if (b === 0) { return '不能除以0!'; } return a / b; }

// 导出多个函数 module.exports = { add, subtract, multiply, divide };

然后在另一个文件里使用:

// app.js const math = require('./math');

console.log(math.add(1, 2)); // 输出: 3 console.log(math.subtract(5, 3)); // 输出: 2 console.log(math.multiply(3, 4)); // 输出: 12 console.log(math.divide(10, 2)); // 输出: 5

四、 exports 简写

还有一种更简洁的写法:

// person.js exports.name = '小明'; exports.age = 18; exports.sayHello = function() { return '大家好,我是' + this.name; };

使用:

const person = require('./person'); console.log(person.name); // 小明 console.log(person.sayHello()); // 大家好,我是小明

不过要注意,exports 只能导出对象属性。如果要导出一个函数或者整个变量,得用 module.exports。

五、 模块加载顺序

Node.js加载模块时有套路:

  1. 先看是不是内置模块(fs, path, http这些)
  2. 再看是不是 node_modules 里的第三方包
  3. 最后看是不是自定义模块(./开头的)

// 这个会先找内置的 fs const fs = require('fs');

// 这个会找 node_modules 里的 express const express = require('express');

// 这个找当前目录下的 user.js const user = require('./user');

六、 实战:做一个计算器模块

来,我们做个完整的例子。

第1步:创建 calculator.js

// calculator.js class Calculator { constructor(name) { this.name = name; }

add(a, b) { return a + b; }

subtract(a, b) { return a - b; }

multiply(a, b) { return a * b; }

divide(a, b) { if (b === 0) return '错误:不能除以0'; return a / b; }

// 打印结果 printResult(operation, a, b, result) { console.log(this.name + ': ' + a + ' ' + operation + ' ' + b + ' = ' + result); } }

module.exports = Calculator;

第2步:创建 main.js

// main.js const Calculator = require('./calculator');

// 创建计算器实例 const calc = new Calculator('我的计算器');

// 做几道题 const result1 = calc.add(10, 5); calc.printResult('+', 10, 5, result1);

const result2 = calc.multiply(3, 7); calc.printResult('*', 3, 7, result2);

const result3 = calc.divide(20, 4); calc.printResult('/', 20, 4, result3);

运行 node main.js,输出:

我的计算器: 10 + 5 = 15 我的计算器: 3 * 7 = 21 我的计算器: 20 / 4 = 5

七、 模块的小坑

1. 循环引用

A引用B,B又引用A,这种情况Node.js能处理,但要注意别死循环:

// a.js console.log('a 开始'); const b = require('./b'); console.log('a 结束');

// b.js console.log('b 开始'); const a = require('./a'); console.log('b 结束');

输出是: a 开始 b 开始 b 结束 a 结束

Node.js会返回一个部分加载的对象,不会死循环。

2. 路径写错

// 错误写法 const foo = require('foo'); // 找不到会报错

// 正确写法 const foo = require('./foo'); // 当前目录 const bar = require('../bar'); // 上级目录

3. 忘了加 .js 后缀

Node.js会自动补全,但最好还是写清楚:

// 这些都行 require('./user') require('./user.js') require('./user.json')

八、 下节预告

这节课我们学了模块系统,下一节我们来聊聊npm这个大杀器,学完你就知道什么叫"站在巨人的肩膀上"——别人写好的代码直接拿来用!

有问题评论区见!