Node系列 · Node基础:基础内置模块
2026/8/17 3:24:09 网站建设 项目流程

Node系列 · Node基础:基础内置模块

Node 内置的核心模块里,os/path/url/util是"几乎每个项目都会用"的四件套。它们不依赖任何第三方包,跨平台行为一致;理解它们的真实行为能避免一类经典的"在我电脑能跑"问题。

一、os:与操作系统交互

os模块提供操作系统层面的查询能力——CPU、内存、用户目录、网络接口等。常用 API:

API返回类型用途
os.EOLstring当前系统的行结束符(\n/\r\n
os.arch()stringCPU 架构('arm64'/'x64'
os.cpus()array每颗逻辑 CPU 核心信息
os.freemem()number空闲内存字节数
os.totalmem()number总内存字节数
os.homedir()string当前用户目录
os.hostname()string主机名
os.tmpdir()string系统临时目录
os.platform()string平台标识('darwin'/'linux'/'win32'
os.uptime()number系统启动到现在的秒数
os.networkInterfaces()object网络接口列表

典型应用:

// 根据 CPU 核心数决定要不要起 worker const cpuCount = os.cpus().length; const workers = Math.max(1, cpuCount - 1); // 把日志写到系统临时目录 const logDir = path.join(os.tmpdir(), 'my-app-logs'); fs.mkdirSync(logDir, { recursive: true });

::: warning
不要拿os.cpus().length当真实物理核心数。它返回的是逻辑核心数(含超线程)。Node 单进程只能用一个 CPU 核心,物理多核需要 Worker Threads 或多进程。
:::

二、path:跨平台路径处理

path模块的核心价值是屏蔽 Windows / POSIX 路径差异。Node 代码里永远不要直接拼字符串路径,全部走pathAPI。

2.1 核心 API

API作用示例
path.basename(p)取文件名path.basename('/a/b/c.txt')'c.txt'
path.dirname(p)取目录path.dirname('/a/b/c.txt')'/a/b'
path.extname(p)取后缀path.extname('/a/b/c.txt')'.txt'
path.join(...p)拼接多段路径path.join('/a', 'b', 'c.txt')'/a/b/c.txt'
path.resolve(...p)解析为绝对路径path.resolve('c.txt')<cwd>/c.txt
path.relative(from, to)计算相对路径path.relative('/a/b', '/a/c/d')'../c/d'
path.isAbsolute(p)是否绝对路径path.isAbsolute('/a')true
path.normalize(p)规范化路径path.normalize('/a//b/./c')'/a/b/c'
path.sep当前系统的路径分隔符Linux\\(实际 /) / Windows\
path.delimiter环境变量分隔符Linux:/ Windows;

2.2joinvsresolve

两个看着像,行为差异很大:

// join:纯拼接,结果是不是绝对路径看输入 path.join('/a', 'b', 'c.txt'); // '/a/b/c.txt' path.join('a', 'b', 'c.txt'); // 'a/b/c.txt' // resolve:从右往左拼,遇到绝对路径就重置起点 path.resolve('a', 'b', 'c.txt'); // <cwd>/a/b/c.txt path.resolve('/a', 'b', '/c.txt'); // '/c.txt'(遇到 /c.txt 重置)

2.3 跨平台注意事项

// ❌ 错误:直接拼字符串 const filePath = __dirname + '/config/' + filename; // ✅ 正确:用 path.join const filePath = path.join(__dirname, 'config', filename); // ❌ 错误:硬编码分隔符 const tmpPath = '/tmp/' + name; // ✅ 正确:用 os.tmpdir() + path.join const tmpPath = path.join(os.tmpdir(), name);

三、url:URL 解析与构造

url模块提供 WHATWG URL 标准实现(Node 10+)。

3.1 核心 API

API用途
new URL(input, base?)构造一个 URL 对象
URLSearchParamsURL 查询字符串解析
url.fileURLToPath(url)file://URL → 路径
url.pathToFileURL(path)路径 →file://URL

3.2 URL 对象

const u = new URL('https://user:pass@example.com:8080/path/to?x=1&y=2#hash'); u.protocol; // 'https:' u.host; // 'example.com:8080' u.hostname; // 'example.com' u.port; // '8080' u.pathname; // '/path/to' u.search; // '?x=1&y=2' u.hash; // '#hash' u.username; // 'user' u.password; // 'pass' u.origin; // 'https://example.com:8080'

3.3 查询参数

const u = new URL('https://example.com/api?x=1&y=2'); // 读取 u.searchParams.get('x'); // '1' u.searchParams.getAll('x'); // ['1'] u.searchParams.has('z'); // false // 增删改 u.searchParams.append('z', '3'); u.searchParams.set('x', '10'); u.searchParams.delete('y'); // 序列化 u.toString(); // 'https://example.com/api?x=10&z=3' // 单独构造 const params = new URLSearchParams({ foo: '1', bar: '2' }); params.toString(); // 'foo=1&bar=2'

3.4 路径与 URL 互转

import { fileURLToPath, pathToFileURL } from 'node:url'; // path → file:// URL pathToFileURL('/usr/local/bin'); // 'file:///usr/local/bin' // file:// URL → path fileURLToPath('file:///usr/local/bin'); // '/usr/local/bin'

ESM 模块下import.meta.urlfile://URL,要拿路径必须fileURLToPath转一次(CJS 下直接是__dirname)。

四、util:工具函数集合

util模块聚集了各种"杂项但有用"的工具。

4.1 类型判断

util.isArray([]); // true util.isDate(new Date()); // true util.isRegExp(/x/); // true util.types.isPromise(Promise.resolve()); // true util.types.isMap(new Map()); // true util.types.isSet(new Set()); // true util.types.isArrayBuffer(new ArrayBuffer(8)); // true

::: tip
Node 10+ 之后Array.isArray/instanceof已经够用,util.isArray等被视为遗留 API。新代码建议用util.types或原生Array.isArray
:::

4.2 回调与 Promise 互转

// 旧的 CJS 回调风格 API:(err, value) => {...} // 想用 async/await?util.promisify 把它包成返回 Promise 的函数 const fs = require('fs'); const readFile = util.promisify(fs.readFile); const data = await readFile('./config.json', 'utf-8'); // 反向:Promise 风格 API 想给老代码用?util.callbackify const asyncAdd = async (a, b) => a + b; const cbAdd = util.callbackify(asyncAdd); cbAdd(1, 2, (err, sum) => { console.log(sum); // 3 });

4.3 继承(inherits

// ES6 class 时代几乎不用——直接用 extends 即可 // 留给老代码理解 function Animal() {} Animal.prototype.greet = function () { return 'hello'; }; function Dog() {} util.inherits(Dog, Animal); Dog.prototype.bark = function () { return 'woof'; }; const d = new Dog(); d.greet(); // 'hello' d.bark(); // 'woof'

4.4 深度严格比较

util.isDeepStrictEqual( { a: 1, b: [1, 2] }, { a: 1, b: [1, 2] } ); // true // 与 '===' 的关键区别:递归比较对象、数组、Map、Set 1 === 1; // true { a: 1 } === { a: 1 }; // false util.isDeepStrictEqual( { a: 1 }, { a: 1 } ); // true

4.5 调试输出

const obj = { a: 1, b: { c: [1, 2, 3] } }; console.log(util.inspect(obj, { depth: 4, colors: true }));

util.inspectconsole.log内部实现,可以指定深度、颜色、隐藏字段等。调试复杂对象时比直接JSON.stringify信息更全(保留函数、undefined、循环引用)。

五、其他常用内置模块速览

模块用途备注
querystringURL 查询字符串URLSearchParams已覆盖大部分场景
assert断言(单元测试)Node 自带测试时用,jest 流行后少用
eventsEventEmitter见第 12 章
stream流处理见第 7 章
crypto加密 / hash见后续章节
zlib压缩 / 解压gzip / deflate
child_process子进程spawn / exec / fork

六、最佳实践

场景推荐做法反例
拼接文件路径path.join/path.resolve字符串+
读用户目录os.homedir()假设是/home/x
写临时文件os.tmpdir()+path.join假设是/tmp
解析 URLnew URL(...)+searchParams手写 split
老 API 转 Promiseutil.promisify自己手写 wrapper
判断内置类型util.typesinstanceof跨 realm 不可靠
多行字符串拼接path.joinos.EOL硬编码\n/\r\n

七、小结

  • os提供系统信息查询;os.cpus().length是逻辑核心数,含超线程
  • path是跨平台路径处理的唯一正确选择;join拼接、resolve解析为绝对路径
  • url用 WHATWG 标准;new URL+searchParams处理查询参数
  • util.promisify把回调 API 包成 Promise;util.callbackify反向
  • 这些模块零依赖——新项目能少装一个包就少装一个

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询