在 Node.js 中,有一些对象和变量可以在任何地方访问,无需使用 require() 引入。它们被称为全局对象(Global Objects)。但需要注意的是,其中一些变量(如 __dirname)实际上是每个模块作用域内的局部变量,但行为上类似于全局变量。本章将详细介绍这些全局对象及其用法。
在浏览器中,全局对象是 window;在 Node.js 中,全局对象是 global。所有全局变量(除了模块自身的变量)都是 global 对象的属性。例如:
console.log(global === globalThis); // true(在大多数环境下)
// 在 REPL 中,var 声明的变量会成为 global 的属性
var foo = 'bar';
console.log(global.foo); // 输出 'bar'
// 但在模块文件中,var 声明的变量只在模块内部,不会添加到 global
从 ECMAScript 2020 开始,globalThis 提供了跨平台访问全局对象的标准方式,无论在浏览器还是 Node.js 中都能使用。
global.console - 控制台对象global.Buffer - 处理二进制数据的类global.setTimeout/clearTimeout - 定时器函数global.setInterval/clearIntervalglobal.setImmediate/clearImmediate - 立即执行(Node.js 特有)global.process - 进程对象global.URL - URL 解析类(需要引入 url 模块,但也可全局访问)var 或 let 声明的变量不会自动成为 global 的属性,它们仅作用于当前模块。要显式创建全局变量,可以将其添加为 global 的属性(例如 global.myVar = 123),但应避免这样做,以免污染全局命名空间。
process 是一个非常重要的全局对象,它提供当前 Node.js 进程的信息和控制能力。常用属性和方法:
console.log(process.pid); // 进程 ID
console.log(process.platform); // 操作系统平台 'win32', 'darwin', 'linux' 等
console.log(process.arch); // CPU 架构 'x64', 'arm' 等
console.log(process.version); // Node.js 版本号
console.log(process.versions); // 各依赖版本(v8, uv, zlib 等)
console.log(process.cwd()); // 当前工作目录
console.log(process.execPath); // Node.js 可执行文件的路径
process.env 包含用户环境变量。可以读取和设置(但设置只影响当前进程,不会影响系统):
console.log(process.env.PATH); // 获取 PATH 环境变量
process.env.MY_VAR = 'hello'; // 临时设置环境变量
常用于配置(如通过 NODE_ENV 区分开发/生产环境)。
process.argv 返回一个数组,包含启动 Node.js 进程时的命令行参数。第一个元素是 Node.js 可执行文件路径,第二个是当前执行的 JavaScript 文件路径,后续是自定义参数。
// 运行 node app.js a=1 b=2
console.log(process.argv);
// 输出类似:
// [
// '/usr/bin/node',
// '/path/to/app.js',
// 'a=1',
// 'b=2'
// ]
process.exit([code]) - 终止进程,可指定退出码(0 表示成功,非 0 表示异常)。process.nextTick(callback) - 将回调推迟到当前操作完成后、事件循环继续之前执行。比 setImmediate 优先级高。process.on('事件', callback) - 监听进程事件,如 exit、uncaughtException、SIGINT 等。process.on('exit', (code) => {
console.log(`进程退出,退出码: ${code}`);
});
process.on('uncaughtException', (err) => {
console.error('未捕获的异常:', err);
process.exit(1);
});
console 用于向标准输出(stdout)或标准错误(stderr)打印信息。常用方法:
console.log('普通日志'); // 换行输出
console.error('错误信息'); // 输出到 stderr
console.warn('警告'); // 同 error
console.info('信息'); // 同 log
const obj = { name: 'Node', type: 'runtime' };
console.dir(obj, { depth: 1, colors: true }); // 以格式化的方式打印对象
console.time('计时器');
// 执行一些操作
console.timeEnd('计时器'); // 输出耗时
console.trace('跟踪'); // 打印当前位置的堆栈跟踪
Buffer 用于处理二进制数据(如文件 I/O、网络通信)。它是 Uint8Array 的子类,提供了一系列操作字节的方法。在 Node.js 中,Buffer 是全局可用的。
// 创建 Buffer
const buf1 = Buffer.alloc(10); // 创建一个长度为10的零填充缓冲区
const buf2 = Buffer.from('Hello', 'utf8'); // 从字符串创建
const buf3 = Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f]); // 从字节数组创建
console.log(buf2.toString('utf8')); // 输出 'Hello'
console.log(buf2[0]); // 输出 104('h' 的 ASCII 码)
// 拼接 Buffer
const buf4 = Buffer.concat([buf2, Buffer.from(' World')]);
console.log(buf4.toString()); // 'Hello World'
Node.js 实现了与浏览器相似的定时器 API,但略有差异(如 setImmediate 是 Node.js 特有的)。
setTimeout(callback, delay[, ...args]) - 延迟执行回调。setInterval(callback, delay[, ...args]) - 周期性执行回调。setImmediate(callback[, ...args]) - 在当前事件循环的末尾执行回调(立即执行,但比 nextTick 晚)。clearTimeout、clearInterval、clearImmediate 用于取消定时器。const timer = setTimeout(() => {
console.log('2秒后执行');
}, 2000);
clearTimeout(timer); // 取消
setImmediate(() => {
console.log('在当前事件循环末尾执行');
});
process.nextTick(() => {
console.log('在当前操作完成后立即执行(比 setImmediate 优先)');
});
以下变量在每个模块中都是可用的,但它们并不是真正的全局对象,而是每个模块的局部变量。然而,由于它们无处不在,通常也归类为“全局”。
__dirname 返回当前模块所在的目录绝对路径。__filename 返回当前模块文件的绝对路径(包含文件名)。
console.log(__dirname); // 例如 /home/user/project
console.log(__filename); // 例如 /home/user/project/app.js
exports 是 module.exports 的引用,用于导出模块的公共接口。module 代表当前模块对象,其中 module.exports 是真正导出的内容。require() 用于引入其他模块、JSON 文件或内置模块。// 导出
exports.sayHello = () => console.log('Hello');
// 等价于
module.exports.sayHello = () => console.log('Hello');
// 引入
const myModule = require('./myModule');
根据 Node.js 版本,还可能存在以下全局对象(或通过 global 访问):
URL 和 URLSearchParams - 用于 URL 解析和操作(需要引入 url 模块,但在较新版本中也可全局访问)。TextEncoder 和 TextDecoder - 用于处理字符串和 Uint8Array 之间的编码转换。performance - 提供高精度时间测量(类似浏览器中的 performance.now())。atob 和 btoa - Base64 编解码(需要引入 buffer 或全局可用?)。这些对象可能不是在所有版本中都默认全局,但可以通过 require() 引入对应的模块使用。
global 对象添加属性,除非你有充分的理由(例如在 polyfill 或调试工具中)。显式依赖导入会使代码更清晰、更易于维护和测试。
在模块文件中,默认启用严格模式("use strict")。在严格模式下,未声明的变量赋值会抛出错误,而且 var 声明的变量不会成为 global 的属性。这有助于避免意外创建全局变量。
本章详细介绍了 Node.js 中的各种全局对象和变量:global、process、console、Buffer、定时器函数,以及模块作用域的 __dirname、require 等。理解这些全局对象对于编写 Node.js 应用程序至关重要。在下一章中,我们将深入探讨 Node.js 的模块系统,学习如何组织和复用代码。