← CLI 命令行 没有下一篇了 →

Node.js 全局对象教程:global、process、Buffer 与模块级变量实战

著
原创 2026-10-11 Node.js 已有人查阅

一、Node.js全局对象是什么

浏览器里有个window对象,挂在它上面的属性和方法可以在页面任何地方访问。Node.js对应的根级对象叫global。挂在global上的变量和函数,在整个应用范围内都能访问,不需要require导入。

但这里有个容易混淆的点:Node.js的“全局”和浏览器的“全局”并不一样。Node.js每个文件是一个模块,模块内声明的变量默认只在该模块作用域内有效。只有显式挂到global上的东西,才真正跨模块共享。

为什么需要全局对象?几个典型场景:

  • 进程管理:process提供进程信息、环境变量、命令行参数;

  • 路径处理:__filename、__dirname定位当前文件和目录;

  • 定时调度:setTimeout、setInterval、setImmediate、queueMicrotask;

  • 二进制数据:Buffer处理文件、网络流等原始字节;

  • 模块系统:exports、require管理模块导入导出。

本节课程知识要点:global是Node.js的根级对象,但模块内变量默认不共享;全局对象的价值在于提供跨模块可访问的基础能力。

二、global与globalThis

2.1global对象

global.message = "这是全局变量";
console.log(message);

输出:

这是全局变量

把message挂到global上之后,当前应用的其他模块也能通过message直接访问。

2.2globalThis对象

globalThis是ECMAScript标准引入的全局对象引用,目的是让同一套代码在浏览器和Node.js里都能拿到全局作用域。

console.log(globalThis === global);
globalThis.message = "欢迎学习代码号编程";
console.log(globalThis.message);

输出:

true
欢迎学习代码号编程

在Node.js中globalThis===global返回true,两者指向同一个对象。

为什么用globalThis而不是global:如果一段代码需要同时跑在浏览器和Node.js环境(比如同构工具库),写globalThis比写global更通用。写global在浏览器里会直接报ReferenceError。

踩坑经历:早期做跨环境工具函数时,我用typeofwindow!=='undefined'?window:global来判断环境,代码又长又容易出错。换成globalThis后一行搞定。但要注意,globalThis在较老的Node.js版本里不存在,如果项目需要兼容旧版本,得先确认运行时版本。

三、console对象

console是全局对象,负责向终端输出日志和调试信息,写入stdout和stderr。

console.log("普通日志");
console.error("错误日志");

输出:

普通日志
错误日志

console.log()写stdout,console.error()和console.warn()写stderr。这个流向差异在重定向日志时很关键。

四、process对象

process代表当前运行的Node.js进程,提供运行时环境信息和控制能力。

console.log("进程 ID:", process.pid);
console.log("Node.js 版本:", process.version);
console.log("当前工作目录:", process.cwd());
console.log("环境变量 NODE_ENV:", process.env.NODE_ENV);

输出类似:

进程 ID: 6934
Node.js 版本: v22.21.1
当前工作目录: /Users/alan/projects/demo
环境变量 NODE_ENV: development

process.pid是进程号,process.version是Node.js版本,process.env读取环境变量,process.cwd()返回当前工作目录。

项目反思:以前我在代码里硬编码配置路径,换环境就出错。后来统一用process.env读取配置,配合.env文件管理,部署时只改环境变量,代码不动。process.env.NODE_ENV也是区分开发和生产行为的常用手段,但注意它只是个字符串,别指望框架自动帮你做所有判断。

五、Buffer对象

Buffer用于在内存中直接处理原始二进制数据,比如文件读写、网络流。

const buffer = Buffer.from("Hello Node.js");
console.log(buffer);

输出是字符串的UTF-8字节的十六进制表示:

<Buffer 48 65 6c 6c 6f 20 4e 6f 64 65 2e 6a 73>

Buffer.from()把字符串转成字节序列。Buffer工作在JavaScript字符串编码体系之外,适合处理非文本数据。

个人建议:处理文本优先用字符串,只有涉及二进制(图片、加密、网络协议)时才用Buffer。混用容易在编码上踩坑,比如把Buffer直接当字符串拼接,结果会变成十六进制文本。

六、内置全局定时器函数

函数 作用
setTimeout() 延迟指定时间后执行一次
setInterval() 每隔指定时间重复执行,直到被清除
setImmediate() 在当前事件循环迭代结束后立即执行
queueMicrotask() 把函数排入微任务队列,在当前操作完成后、事件循环继续前执行

看一个综合示例:

console.log("代码号编程定时器示例");

setTimeout(() => {
  console.log("setTimeout()");
}, 0);

const interval = setInterval(() => {
  console.log("setInterval()");
  clearInterval(interval);
}, 1000);

setImmediate(() => {
  console.log("setImmediate()");
});

queueMicrotask(() => {
  console.log("queueMicrotask()");
});

console.log("End");

输出顺序大致为:

代码号编程定时器示例
End
queueMicrotask()
setImmediate()
setTimeout()
setInterval()

执行顺序拆解:

  1. 同步代码先跑:打印标题和End;

  2. queueMicrotask()排在微任务队列,当前同步代码结束后立即执行;

  3. setImmediate()在当前事件循环迭代的check阶段执行;

  4. setTimeout(...,0)进入timers阶段,实际会有最小延迟;

  5. setInterval()在1秒后触发,执行一次后立即清除。

注意:setImmediate()和setTimeout()的先后顺序在不同执行上下文和事件循环状态下可能变化,不要依赖固定顺序做业务逻辑。

七、模块相关全局变量

这些变量在每个模块里都能用,管理文件路径和模块导入导出。

变量/函数 说明
__dirname 当前模块所在目录的绝对路径
__filename 当前模块文件的绝对路径
exports 导出函数、对象或值的快捷方式
require() 加载模块,使用其导出的功能

示例:

maths.js

console.log("__dirname:", __dirname);
console.log("__filename:", __filename);
exports.add = (a, b) => a + b;

app.js

const maths = require("./maths");
console.log("sum:", maths.add(10, 20));

输出类似:

__dirname: C:\Projects\NodeApp
__filename: C:\Projects\NodeApp\maths.js
sum: 30

__dirname和__filename显示maths.js的目录和文件路径;exports导出add()函数;require()在app.js里加载该模块并调用。

踩坑经历:__dirname在CommonJS模块里可用,但在ESModule(.mjs或"type":"module")里不存在。迁移项目时我遇到一批文件报__dirnameisnotdefined,后来改用import.meta.url配合fileURLToPath转换。如果项目混用两种模块规范,这个差异要提前注意。

八、现在Node.js的Web平台全局API

较新的Node.js版本引入了浏览器风格的全局API,服务端也能直接用。

全局API 说明
fetch() 发送HTTP请求并接收响应
URL 创建和操作URL
URLSearchParams 解析和管理URL查询参数
Request 表示HTTP请求
Response 表示HTTP响应
Headers 操作HTTP头
FormData 创建和管理表单数据
AbortController 取消异步操作
structuredClone() 创建对象的深拷贝

示例:

const params = new URLSearchParams({ page: "1", size: "10" });
console.log(params.toString());

const copy = structuredClone({ name: "代码号", tags: ["node", "js"] });
copy.tags.push("global");
console.log(copy);

输出:

page=1&size=10
{ name: '代码号', tags: [ 'node', 'js', 'global' ] }

structuredClone()做深拷贝比JSON.parse(JSON.stringify(obj))更可靠,能处理Date、Map、Set等类型。

为什么不用JSON深拷贝:JSON.parse(JSON.stringify())会丢失undefined、函数、Date对象会变成字符串、循环引用直接报错。structuredClone()支持这些类型,还支持循环引用。

九、项目实例:跨模块共享配置

下面这段代码用全局对象和模块变量做一个轻量配置读取。

config.js

exports.load = () => ({
  env: process.env.NODE_ENV || "development",
  cwd: process.cwd(),
  version: process.version
});

app.js

const config = require("./config").load();
console.log("运行环境:", config.env);
console.log("工作目录:", config.cwd);
console.log("Node 版本:", config.version);

运行NODE_ENV=productionnodeapp.js,输出类似:

运行环境: production
工作目录: /Users/alan/projects/demo
Node 版本: v22.21.1

这里用到了process.env、process.cwd()、process.version和require(),都是全局对象或模块级全局能力。这种写法适合脚本和小工具,项目规模大了之后建议换成专门的配置管理模块。

十、本节课程知识要点

  • global是Node.js根级对象,globalThis是跨环境标准写法,两者在Node.js中指向同一对象。

  • console写stdout/stderr,是调试和日志的基础入口。

  • process提供进程信息、环境变量、命令行参数和运行时控制。

  • Buffer处理原始二进制数据,文本场景优先用字符串。

  • 定时器函数分同步、微任务、宏任务三个层次,执行顺序受事件循环阶段影响。

  • __dirname、__filename、exports、require是模块级全局变量,CommonJS和ESModule下行为不同。

  • fetch、URL、structuredClone等Web平台API已进入Node.js,使用前确认运行时版本。

  • 挂到global上的变量跨模块共享,但滥用会污染全局作用域,项目里优先用模块导出。

← Node.js 命令行选项详解:31个CLI参数实战指南与分类速查 没有下一篇了 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号