FORMA

全局对象与变量

Node.js 提供模块内可直接使用的全局对象;与浏览器 window 不同,模块顶层的 const/let 不会挂到 global。见 后端入门概览模块系统

1. global

  • 作用:全局命名空间对象,类似于浏览器中的 window。在 Node.js 的 REPL 环境中或任意模块中,可以通过 global 访问全局作用域。
  • 注意:在模块文件中,varletconst 声明的变量不会成为 global 的属性,只属于模块局部作用域。如果想定义真正的全局变量,需显式赋值给 global(通常不推荐,避免命名冲突)。
js
// 不会挂载到 global
var a = 1;
console.log(global.a); // undefined

// 显式挂载
global.b = 2;
console.log(global.b); // 2

Node.js 内置的一些全局 API 实际上是 global 的属性,例如 consolesetTimeout

2. __dirname

  • 作用:返回当前模块文件所在的目录的绝对路径
  • 注意:在 ES 模块(使用 .mjs 文件或 "type": "module".js 文件)中,__dirname 不可用,需要通过 import.meta.url 手动构造。
js
// example.js 位于 /home/user/project/src
console.log(__dirname); // 输出: /home/user/project/src

ES 模块替代方案

js
import { fileURLToPath } from "url";
import { dirname } from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

3. __filename

  • 作用:返回当前模块文件的绝对路径(包含文件名和扩展名)。
  • 注意:同样,ES 模块中不可直接使用,需通过 import.meta.url 获取。
js
// /home/user/project/src/example.js
console.log(__filename);
// 输出: /home/user/project/src/example.js

4. module

  • 作用:是一个指向当前模块的引用。每个 Node.js 文件都是一个模块,module 对象包含了该模块的元信息,如 idpathexportsparentchildren 等。
  • 常见属性
    • module.exports:模块导出的内容(核心)。
    • module.id:模块标识符,通常是文件路径。
    • module.loaded:模块是否加载完成。
js
console.log(module.id); // 模块的完整路径
console.log(module.paths); // 模块查找路径数组

5. exports

  • 作用exportsmodule.exports 的一个引用。通过它可以方便地导出模块内容。最终暴露给外部的是 module.exports
  • 注意:直接对 exports 赋值会切断与 module.exports 的联系,使导出失效。必须始终通过 module.exportsexports.xxx 添加属性。
js
// 正确用法
exports.foo = "bar";
module.exports.baz = "qux";

// 错误用法(会丢失导出)
exports = { foo: "bar" }; // 此时 exports 不再指向 module.exports

如果只需要导出一个函数或对象,推荐直接使用 module.exports = ...

6. require

  • 作用:用于加载其他模块的核心函数。参数可以是模块名、相对路径或绝对路径。
  • 机制
    • 支持加载 .js.json.node(C++ 插件)文件。
    • 加载 JSON 文件时会自动解析为对象。
    • 具有缓存机制:多次 require 同一个模块只会执行一次,返回相同的 exports 对象。
    • 可以通过 require.resolve 获取模块的完整路径,而不实际加载模块。
js
const fs = require("fs"); // 加载内置模块
const myModule = require("./mod"); // 加载本地模块(可省略 .js)
const data = require("./data.json"); // 加载 JSON

查找规则:Node.js 会从当前文件目录开始,依次查找 node_modules 目录,直到文件系统根目录。

7. process

  • 作用:提供当前 Node.js 进程的信息和控制能力。它是 EventEmitter 的实例,可以监听进程事件。
  • 常用属性与方法
    • process.argv:命令行参数数组。
    • process.env:环境变量对象。
    • process.cwd():返回当前工作目录。
    • process.exit(code):退出进程。
    • process.on('uncaughtException', callback):捕获未处理的异常。
    • process.nextTick(callback):将回调推迟到事件循环的下一个阶段执行(比 setImmediate 优先级高)。
    • process.platform:操作系统平台(如 'win32''linux')。
    • process.version:Node.js 版本号。
js
// 打印所有环境变量
console.log(process.env);

// 监听退出事件
process.on("exit", code => {
    console.log(`进程退出,退出码:${code}`);
});

// 使用 nextTick
process.nextTick(() => {
    console.log("在事件循环当前阶段结束后执行");
});

8. Buffer

  • 作用:用于处理二进制数据(如文件流、网络数据)。在 TCP 流或文件操作中,数据的传输通常以 Buffer 形式进行。
  • 特点
    • Buffer 是 Node.js 全局类,无需 require
    • 在 ES6 引入 TypedArray 之前,Buffer 是 Node.js 处理二进制的主要方式,现在它实现了 Uint8Array 接口。
    • Buffer 的大小在创建时就固定,无法动态调整。
  • 常用方法
    • Buffer.from(array) / Buffer.from(string):从数组或字符串创建 Buffer。
    • Buffer.alloc(size):创建指定大小的零填充 Buffer。
    • buf.toString(encoding):将 Buffer 转换为字符串(默认 'utf8')。
    • buf.length:Buffer 的字节长度。
js
// 创建 Buffer
const buf1 = Buffer.from("Hello", "utf8");
console.log(buf1); // <Buffer 48 65 6c 6c 6f>

const buf2 = Buffer.alloc(5); // 长度为 5 的零填充 Buffer
buf2.write("Hi"); // 写入数据

// 合并两个 Buffer
const combined = Buffer.concat([buf1, buf2]);
console.log(combined.toString()); // "HelloHi"

注意:Node.js 中很多 API 既接受 string 也接受 Buffer,例如 fs.readFile 可以返回 Buffer。

相互关系与注意事项

  • exports vs module.exports:初始化时 exportsmodule.exports 指向同一个对象。若只添加属性,两者皆可;若要导出对象本身,必须用 module.exports
  • require 的缓存:模块首次加载后会被缓存,因此模块内的全局变量不会重复初始化,但也意味着需要小心模块状态的共享。
  • __dirname__filename:在 CommonJS 模块中可用,在 ES 模块中需自行构造。
  • process.nextTick:它在当前事件循环阶段结束时立即执行,优先级高于 setImmediatePromise 微任务,但 Promise 的微任务会在 nextTick 之前执行(取决于 Node.js 版本,实际顺序:nextTick 队列 > 微任务队列 > 其他阶段)。

参考文献

以下链接在编写时均可正常访问:

资料说明
Globals官方
process进程对象
ModulesCommonJS

相关文章

Series

base

4 / 4

模块系统