Node.js:global(全局变量)

Node 文件顶层能直接写的名字,并不都是「全局变量」。一类挂在进程的全局对象上,每个模块拿到的是同一份;另一类只在当前 CommonJS 文件里有,由模块包装函数当形参注入,换一个文件就是另一套值。把两类混在一起,会把 exports__dirname 误当成 global 上的属性。

全局变量

真全局属于 整个 Node 进程:语言自带的(如 Objectundefined),以及 Node 挂上去的(如 processBuffer)。它们是 global(也就是 globalThis)上的属性,任意模块里读到的是同一个对象。

浏览器里脚本顶层就是全局作用域,var something 会挂到全局。Node 的 CommonJS 和 ESM 顶层都不是全局作用域var something 只在当前模块里。要真正挂到进程全局,应写 global.somethingglobalThis.somethingglobalThis 在浏览器和 Node 都能用;在 Node 里它就是 global

往全局挂自定义变量会污染所有模块,应用代码应优先用模块导出。

global

Node.js 的全局命名空间对象。上面说的真全局,都可以写成 global.processglobal.Buffer 这种形式,只是平时省略了前缀。

process

描述并控制当前 Node 进程:环境变量、argv、标准流、退出码等。无需 require。ESM 里同样是全局(也可 import process from 'node:process')。

Buffer 类

用来直接处理二进制数据。仍是全局构造器,也可以 require('node:buffer')。不要再用已删除的 new Buffer(),一律 Buffer.allocBuffer.from

  • Buffer.alloc(size[, fill[, encoding]])
  • Buffer.allocUnsafe(size)
  • Buffer.allocUnsafeSlow(size)
  • Buffer.byteLength(string[, encoding])
  • Buffer.compare(buf1, buf2)
  • Buffer.concat(list[, totalLength])
  • Buffer.from(array)
  • Buffer.from(arrayBuffer[, byteOffset[, length]])
  • Buffer.from(buffer)
  • Buffer.from(string[, encoding])
  • Buffer.isBuffer(obj)
  • Buffer.isEncoding(encoding)
  • Buffer.poolSize

Console 类

console 模块提供调试输出,类似浏览器控制台。

它导出两块:

  • Console 类logerrorwarn 等,可以写到任意可写流。
  • 全局 console 实例:默认写到 process.stdoutprocess.stderr。全局 console 的方法 既不保证总是同步(和浏览器不同),也不保证总是异步(和其他 Node 流不同)。

可自己指定输出流:

const { Console } = require('console');
// 或者
const { Console } = console;
const logger = new Console(process.stdout, process.stderr);
  • new Console(stdout[, stderr][, ignoreErrors])
  • console.assert(value[, message][, ...args])
  • console.clear()
  • console.count([label])
  • console.countReset([label])
  • console.debug(data[, ...args])
  • console.dir(obj[, options])
  • console.error([data][, ...args])
  • console.group([...label])
  • console.groupCollapsed()
  • console.groupEnd()
  • console.info([data][, ...args])
  • console.log([data][, ...args])
  • console.time(label)
  • console.timeEnd(label)
  • console.trace([message][, ...args])
  • console.warn([data][, ...args])

setImmediate(callback[, ...args])

callback 排进事件循环的 check 阶段。同一轮里多次 setImmediate 按登记顺序跑完这一轮队列。若在 正在执行的 immediate 回调里setImmediate,要等到 下一轮 check。

setTimeout(fn, 0) 看起来很像,但走的是 timers 阶段。Node 会把小于 1 的 delay 当成 1 毫秒。两者谁先跑,取决于调用时所在的阶段:

  • 在文件 I/O、网络 I/O 等回调里:本轮会先进入 check,setImmediate 先于 setTimeout(fn, 0)(浏览器事件循环不是这套,不要套过来)。
const fs = require('fs');
fs.readFile(__filename, () => {
  setTimeout(() => {
    console.log('1');
  }, 0);
  setImmediate(() => {
    console.log('2');
  });
});
// 2
// 1
  • 在主模块同步代码里:两个都只是「排期」,顺序不固定。timers 的 1ms 到了没、以及何时离开 poll,都会影响结果。
setTimeout(() => {
  console.log('1');
}, 0);
setImmediate(() => {
  console.log('2');
});
// 顺序不固定

clearImmediate(immediate)

取消 setImmediate() 返回的 Immediate。

setInterval(callback, delay[, ...args])

每隔 delay 毫秒重复执行 callback

delay 大于 2147483647 或小于 1 时按 1 处理;非整数会截成整数。

clearInterval(timeout)

取消 setInterval() 返回的 Timeout。

setTimeout(callback, delay[, ...args])

大约在 delay 毫秒后执行一次 callback。Node 不保证刚好在那一毫秒触发,也不保证和别的定时器的先后,只保证尽量靠近指定时间。

delay 大于 2147483647 或小于 1 时按 1 处理;非整数截成整数。

clearTimeout(timeout)

取消 setTimeout() 返回的 Timeout。

注意: Node 里 setImmediatesetIntervalsetTimeout 返回的是 对象;浏览器里返回的是正整数编号。

其他现行全局

这些同样是进程级的,不是包装函数注入的:

  • globalThisqueueMicrotask
  • URLURLSearchParamsTextEncoderTextDecoderAbortControllerBlobEventEventTarget
  • fetchHeadersRequestResponse(Node 18 起默认可用)
  • structuredCloneperformanceperf_hooks 那套时间原点)
  • crypto 作为 Web Crypto 全局(与 require('node:crypto') 不是同一个模块对象,但经常一起出现)

模块包装函数注入的名字

CommonJS 加载一个 .js 文件时,不会把文件当全局脚本跑,而是包进一个函数再调用。五个形参就是下面这些名字:

(function (exports, require, module, __filename, __dirname) {
  // 当前文件的源码在这里执行
});

因此它们 不是 global 上的属性,只在 当前这个 CJS 文件 的作用域里有效。换一个文件,包装函数会再调一次,五个参数换成那份文件自己的。

console.log(global.require);   // undefined
console.log(typeof require);   // 'function',来自包装函数形参

ESM("type": "module".mjs)没有这层包装,也就没有这五个名字。目录和文件名用 import.meta.dirnameimport.meta.filename(Node 20.11+),或用 import.meta.url 自己算:

import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

加载别的模块用 import;需要 CJS 的 require 时再用 createRequire(import.meta.url)

参考资料

Globals(Node.js 文档)

Timers

setTimeout 和 setImmediate 与 Event Loop

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-09-02 01:41:11

results matching ""

    No results matching ""