Node.js 全局对象完整清单(附:各对象作用速查表)

Node.js 的全局对象分两类:真正全局(CJS/ESM 通用)约 13 个,伪全局(仅 CommonJS 可见)5 个。真正全局里最常用的是 process、console、Buffer、定时器四件套、WHATWG Web API;伪全局则是 __dirname、__filename、require、module、exports 这一组老朋友。下面把每个对象的作用、典型用法、踩坑提醒三件事一次说清。

真正全局:跨模块、跨标准都可用

这些对象在 CommonJS 和 ESM 里都不需要 import,直接用即可。它们都挂在 globalThis 上,浏览器兼容的部分还能在 Deno、Bun 里复用。

global / globalThis

Node 没有浏览器的 window,globalThis 就是全局命名空间的根,global 是它的历史别名。新代码统一用 globalThis(ES2020 标准),从 Node 12 起原生支持。

// 任何模块、任何位置直接访问
console.log(globalThis.process === process); // true
globalThis.__APP_START__ = Date.now();

注意:向 globalThis 挂自定义变量会产生跨模块状态污染,多个测试用例之间可能互相干扰。非要共享,建议用 Symbol.for('appName') 命名或单独建一个配置模块。

process

当前 Node 进程的单例对象。日常用得最多的成员:

  • process.env:环境变量(process.env.NODE_ENV、process.env.PORT,全部是字符串)
  • process.argv:命令行参数数组
  • process.cwd():当前工作目录(与 __dirname 不一定相同)
  • process.exit(code):退出进程,code=0 正常退出
  • process.on('uncaughtException', cb) / process.on('unhandledRejection', cb):捕获未处理异常与 Promise 拒绝
  • process.nextTick(cb):在事件循环微任务之前插入回调,慎用

process.env.PORT 永远返回字符串或 undefined,做算术前记得 Number() 强转,否则 "3000" + 1 会变成 "30001"。

console

标准输出与标准错误的封装。常用方法:

  • console.log / info / warn / error / debug:分别走 stdout / stderr
  • console.time(label) 与 console.timeEnd(label):性能计时
  • console.table(obj):把对象/数组以表格形式打印
  • console.trace():打印当前位置的调用栈

Node 里 console.log 写入 TTY 时是同步的,写入文件或管道时是异步的,调试高并发日志要留意——别在大循环里靠 console.log 限流,没用。

Buffer

V8 堆外的一段固定长度二进制内存。两种创建方式:

const a = Buffer.alloc(8);           // 8 字节的零填充
const b = Buffer.from('hello');       // 从字符串创建(默认 UTF-8)
const c = Buffer.from([0x68, 0x69]);  // 从字节数组创建

fs 与 net 模块默认返回 Buffer,转字符串用 buf.toString('utf8')。Buffer 早于 Uint8Array 出现,Node 里仍是事实标准;新代码里跟标准交互的部分建议用 Uint8Array(Buffer 是它的子类,混用基本无障碍)。

setTimeout / setInterval / setImmediate 与对应的 clear* 系列

定时器四件套,行为各有不同:

  1. setTimeout(cb, ms):最少 ms 毫秒后执行一次(受系统调度粒度影响,实际通常 ≥1ms)
  2. setInterval(cb, ms):按 ms 间隔重复执行(受事件循环繁忙度影响,实际间隔可能更大)
  3. setImmediate(cb):当前事件循环迭代结束、I/O 回调之后立即执行
  4. setTimeout(cb, 0):等价于 setImmediate 吗?不完全等价——setTimeout(0) 最小延迟 1ms,setImmediate 严格在 I/O 之后

返回值都是 Timeout 对象,传给对应 clear* 可取消。在 I/O 密集场景里优先 setImmediate 避免定时器被饿死。

queueMicrotask(cb)

把回调插入 V8 微任务队列。语义上等价于 Promise.resolve().then(cb),但不需要包装 Promise,常用于确保回调异步执行且顺序可控。

注意:process.nextTick 优先级高于微任务队列,过度使用会造成「nextTick 饥饿」、阻塞 I/O。新代码优先用 queueMicrotask,只在确实需要在微任务之前插入时才用 nextTick。

URL / URLSearchParams / URLPattern

WHATWG URL 标准实现,从 Node 10 起逐步引入。

const u = new URL('https://a.com/b?x=1&y=2');
console.log(u.host, u.pathname, u.searchParams.get('x'));
// 'a.com' '/b' '1'

const pat = new URLPattern('/api/:id', 'https://a.com');
console.log(pat.test('https://a.com/api/42')); // true

URLSearchParams 处理查询串、URLPattern 声明路由模式(Node 23 实验性),都是真正全局。

TextEncoder / TextDecoder

WHATWG 文本编解码。TextEncoder 把字符串编码为 Uint8Array,默认 UTF-8;TextDecoder 反向解码并支持 stream: true 流式解码。

跟 Buffer 配合完成字符串与二进制的互转:

const enc = new TextEncoder().encode('hi');           // Uint8Array
const dec = new TextDecoder().decode(enc);            // 'hi'

fetch / Request / Response / Headers / FormData

浏览器兼容 HTTP 实现。从 Node 18 起 fetch 升级为真正全局,底层由 undici 实现。除了发请求,服务端也能直接构造 Response 对象返回自定义响应,常用于 Service Worker 风格的中间件或测试桩。

const r = await fetch('https://api.example.com/data');
const j = await r.json();

配套的 AbortController / AbortSignal 也全局化了,可取消 fetch 与其他基于 Promise 的操作。

structuredClone(value)

浏览器兼容深拷贝。从 Node 17 起全局可用,能克隆大多数 JS 值(不包括函数、Symbol、原型链上的 DOM 节点),是 JSON.parse(JSON.stringify(obj)) 的安全替代——后者会丢 Date、丢 undefined、丢循环引用。

const a = { x: new Date(), y: [1,2], z: undefined };
const b = structuredClone(a); // 完全独立副本

Serverless 场景下常用它跨异步上下文传递深嵌套数据。

performance

性能时间线 API。performance.now() 返回亚毫秒精度相对时间(自进程启动起),比 Date.now() 更适合做耗时测量。

PerformanceObserver 可订阅各种 PerformanceEntry,对性能监控与告警有用。底层是 perf_hooks 模块,但 performance 本身已全局化。

WebAssembly

浏览器兼容编译执行容器。WebAssembly.instantiate(bufferSource) 在 Node 里加载 .wasm 二进制并执行,可与 C/C++/Rust 写的模块互通,常用于性能敏感计算(图像处理、加密、压缩)。

const buf = await fs.promises.readFile('module.wasm');
const { instance } = await WebAssembly.instantiate(buf);
console.log(instance.exports.add(1, 2)); // 3

navigator

部分浏览器 API 适配,便于同一份代码同时在浏览器和 Node 运行。常用属性:

  • navigator.userAgent:'Node.js/22.9.0' 之类
  • navigator.hardwareConcurrency:逻辑 CPU 数
  • navigator.languages:默认语言列表

不强求使用,只是跟浏览器代码兼容时方便。

伪全局:仅在 CommonJS 中可见

Node 启动 CommonJS 文件时,会用 (function(exports, require, module, __filename, __dirname) { ... }) 把源码包起来,于是这 5 个变量「看起来是全局」。在 ESM(.mjs 或 "type": "module")里它们全部不存在。

__dirname

当前模块文件所在目录的绝对路径。注意跟 process.cwd() 区别:__dirname 跟着文件走、cwd() 跟着执行命令的目录走,两者经常不同。

ESM 替代:path.dirname(fileURLToPath(import.meta.url))。

__filename

当前模块文件的绝对路径,含文件名。

ESM 替代:fileURLToPath(import.meta.url)。

require(id)

同步加载模块,CommonJS 的核心。常用方法:

  • require.resolve(id):返回解析后的文件路径(不实际加载)
  • require.cache:模块缓存对象,删键可强制重载(慎用)
  • require.main:入口模块引用,可判断当前文件是否被 node 直接执行

ESM 替代:import ... from '...'(异步、静态分析、tree-shaking 友好)。

module

当前模块的引用。module.exports 设置模块对外暴露内容,是 CommonJS 的导出机制核心。

exports

module.exports 的简写形式。但给 exports 整体赋值为新对象会切断它与 module.exports 的连接——这是新手最常踩的坑:

// 错误:外部拿到的是 {}
exports = { foo: 1 };

// 正确:修改 exports 的属性
exports.foo = 1;
// 或:直接覆盖 module.exports
module.exports = { foo: 1 };

速查对照表

按”是否真正全局 × 是否支持 ESM”两个维度,把上面 18 个对象分四档:

对象 / 变量 类型 挂 globalThis CJS 可用 ESM 可用 引入版本
globalThis / global 命名空间 是 是 是 0.1.27 / 12.0.0
process 进程单例 是 是 是 0.1.7
console 日志 是 是 是 0.1.100
Buffer 二进制 是 是 是 0.1.103
setTimeout / setInterval / setImmediate 定时器 是 是 是 0.0.1 / 0.9.1
queueMicrotask 微任务 是 是 是 11.0.0
URL / URLSearchParams URL 解析 是 是 是 10.0.0
TextEncoder / TextDecoder 编解码 是 是 是 11.0.0
fetch / Request / Response HTTP 是 是 是 18.0.0
structuredClone 深拷贝 是 是 是 17.0.0
performance 时间 是 是 是 8.5.0(全局化 16.0.0)
WebAssembly 编译执行 是 是 是 8.0.0
navigator 环境信息 是 是 是 21.0.0
__dirname / __filename 路径 否 是 否 —
require / module / exports 模块 否 是 否 —

常见问题(FAQ)

Q1:global 和 globalThis 有什么区别?

global 是 Node 专属全局命名空间,globalThis 是 ES2020 标准、跨环境(浏览器 / Node / Deno / Bun)通用的根对象。新代码统一用 globalThis,老代码用 global 也不影响。

Q2:ESM 里怎么拿到当前文件目录?

两步:import.meta.url 拿到当前文件的 URL,path.dirname(fileURLToPath(import.meta.url)) 把 URL 转成目录路径,赋给 __dirname 即可。

Q3:process.nextTick 和 queueMicrotask 该用哪个?

优先 queueMicrotask。process.nextTick 不在 V8 微任务队列中、也不受 I/O 调度约束,过度使用会阻塞事件循环;queueMicrotask 走标准微任务队列,行为可预测、与浏览器一致。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
小码农的头像小码农认证作者

相关推荐

返回顶部