如何在nodejs定义全局变量呢?
- 我们平时定义全局变量是采用
var
关键字来进行定义的,而这里正常定义的全局变量是放在window全局对象之下的
- 但在Node中,是没有window这个对象的
1. 使用 global 对象
Node.js 中的 global
对象是一个全局命名空间对象。在任何模块中给 global
对象添加属性,都会使这些属性成为全局可访问的变量。
// 定义一个全局变量
global.myGlobalVar = 'Hello, xiaoyu!';
// 在另一个文件或模块中访问这个全局变量
console.log(myGlobalVar); // 输出: Hello, xiaoyu!
- 需要注意的是,我们不能够在终端中打印node2.js,因为模块化有主次,是node2变成了node1的一部分模块,但node2本身是不和node1产生联系的,除非我们导出(下面第三点做法)。
- 全局可访问的意思是,该变量能够被导入进来的模块所识别。
全局变量的初始化
- 全局变量应在使用之前被初始化。如果尝试访问一个未定义的全局变量,Node.js 会抛出
ReferenceError
。 - 在一个模块中向
global
对象添加属性来创建全局变量时,这个变量只有在该语句执行之后才可用。
模块加载和执行顺序
- 当使用
require
加载一个模块时,Node.js 会同步执行该模块的代码。这意味着在require
调用返回之前,被加载模块中所有顶层代码都会执行。 - 如果模块中定义了全局变量(通过
global
),那么这些变量将在require
完成之后立即可用。 - 如果在模块 A 中
require
了模块 B,并且模块 B 定义了全局变量,那么在模块 A 的require
调用之后(即模块 B 的代码执行完毕后)这些全局变量才在模块 A 中可用。
循环依赖
- 如果两个或多个模块互相
require
,可能会出现循环依赖的情况,这会影响模块的加载顺序和变量的初始化顺序。 - Node.js 有一套机制来处理循环依赖,但在这种情况下依赖的解析可能不是我们所期望的。可能导致一些变量在尝试访问它们时还未被定义。
延迟初始化
- 如果一个全局变量的初始化依赖于异步操作(如文件读取、数据库查询等),那么即使全局变量已经被定义,它的值也可能在模块的其余代码执行时还未准备好。
- 对于这种情况,应该使用回调、Promise 或 async/await 来确保变量在使用前已经被正确初始化。
2. 在模块顶层声明变量
虽然这不是一个严格意义上的全局变量,但在模块的顶层(而不是在任何函数内部)声明的变量,在该模块的所有地方都是可访问的。如果这个模块被其他多个模块导入,那么这个变量在导入它的所有模块中也都是可访问的。
// 在模块顶层声明变量
let moduleVar = 'This is accessible within this module';
// 该变量可以在模块的任何地方使用
function logVar() {
console.log(moduleVar);
}
logVar(); // 输出: This is accessible within this module
3. 将变量挂载到 global 对象并导出
如果希望在一个模块中定义全局变量,并确保它在其他模块中也是可访问的,可以先将变量挂载到 global
对象,然后从模块中导出它。
// module1.js
global.myGlobalVar = 'Hello from module 1';
module.exports = global.myGlobalVar;
// app.js
require('./module1');
console.log(myGlobalVar); // 输出: Hello from module 1
注意事项
- 在全局命名空间中定义变量应当非常小心,以避免不同模块间的命名冲突。
- 过度使用全局变量可能会导致代码难以维护和理解,尤其是在大型项目中。
- 全局变量在整个应用的生命周期内都是存在的,可能会导致意外的副作用和内存泄漏。
- 考虑使用其他模式,如模块导出或使用类和构造函数,来共享和重用代码,而不是依赖全局变量。
GlobalThis的使用
- 我们知道,window和global分别是浏览器和node的不同全局对象形式,这会导致一个比较麻烦的问题,就是如果我们要开发一个第三方库,要兼容node或者是浏览器环境就会很麻烦,所以在ECMA script2020的时候,提供了globalThis这个API,能够同时作用在浏览器和node环境
- 环境无关性:
globalThis
提供了一个统一的方式来引用全局对象,无论代码是运行在浏览器、Node.js 还是其他任何支持 ECMAScript 的环境中。他会根据具体的环境自己判断是使用window还是global
- 简化代码:使用
globalThis
可以使代码更加简洁明了,不再需要通过不同的全局对象名称来兼容多环境。
// 定义一个全局变量
globalThis.myGlobalVar = 'Hello, world!';
// 在任何支持 ECMAScript 的环境中访问这个全局变量
console.log(globalThis.myGlobalVar); // 输出: Hello, world!
- 兼容性:需要注意的是,虽然
globalThis
在最新的 JavaScript 环境中得到了支持,但在一些旧环境中可能还不可用。在使用globalThis
之前,需要考虑目标环境的兼容性。
关于其他全局API
由于nodejs中没有DOM和BOM,除了涉及到DOM和BOM的这些API用不了,其他的ECMAscriptAPI基本都能用
nodejs内置全局API
- 直接就能用的两个变量,获取关于目录和当前文件的信息
__dirname | __filename |
---|---|
表示当前模块的所在目录 的绝对路径 |
表示当前模块文件 的绝对路径,包括文件名和文件扩展名 |
process
process
是一个全局对象,提供了当前 Node.js 进程的信息,并对其进行控制。由于它跟上面两个获取文件名和目录一样是全局可访问的,所以我们可以在任何 Node.js 程序中直接使用它而无需通过 require
导入。
- process.env:一个包含用户环境信息的对象。例如,
process.env.PATH
提供当前的环境变量PATH的值。 - process.argv:一个数组,包含启动 Node.js 进程时传递的命令行参数。
process.argv[0]
通常是node
的路径,process.argv[1]
是正在执行的 JavaScript 文件的路径,其余的是任何额外的命令行参数。 - process.exit([code]):使用指定的
code
终止当前进程。如果省略,code
默认为 0,表示成功完成。 - process.cwd():返回 Node.js 进程的当前工作目录。
- process.nextTick(callback, […args]):将
callback
添加到下一个时间点的事件循环队列中。这意味着一旦当前事件循环队列的所有任务完成,nextTick
队列中的所有回调都将被依次调用。 - process.uptime():返回 Node.js 进程已运行的秒数。
- process.memoryUsage():返回一个对象,描述了 Node.js 进程的内存使用情况,如堆内存使用量和外部内存使用量。
// 获取环境变量
console.log(process.env);
// 输出: 当前进程的环境变量对象
// 获取命令行参数
console.log(process.argv);
// 输出: 包含启动 Node.js 进程时传递的命令行参数的数组
// 获取当前工作目录
console.log(process.cwd());
// 输出: Node.js 进程的当前工作目录
// 终止当前进程
// process.exit(0);
// 注意:执行此命令将会终止进程,因此其他示例代码将不会执行。
// 将回调函数放入下一个事件循环中执行
process.nextTick(() => {
console.log('Next tick callback executed');
});
// 输出: "Next tick callback executed",此消息将在当前事件循环结束后、下一个事件循环开始时输出
// 获取 Node.js 进程的运行时间
console.log(`Uptime: ${process.uptime()} seconds`);
// 输出: Node.js 进程已运行的秒数
// 获取 Node.js 进程的内存使用情况
console.log(process.memoryUsage());
// 输出: 描述 Node.js 进程内存使用情况的对象,如堆内存使用量
// 注册 'exit' 事件的监听器
process.on('exit', (code) => {
console.log(`Exiting with code: ${code}`);
});
// 当进程退出时,输出退出码
原文链接:https://juejin.cn/post/7353561676089753615 作者:XiaoYu2002