likes
comments
collection
share

Node 第十章 全局变量

作者站长头像
站长
· 阅读数 7

如何在nodejs定义全局变量呢?

  • 我们平时定义全局变量是采用var关键字来进行定义的,而这里正常定义的全局变量是放在window全局对象之下的

Node 第十章 全局变量

  • 但在Node中,是没有window这个对象的

1. 使用 global 对象

Node.js 中的 global 对象是一个全局命名空间对象。在任何模块中给 global 对象添加属性,都会使这些属性成为全局可访问的变量。

// 定义一个全局变量
global.myGlobalVar = 'Hello, xiaoyu!';

// 在另一个文件或模块中访问这个全局变量
console.log(myGlobalVar); // 输出: Hello, xiaoyu!

Node 第十章 全局变量

  • 需要注意的是,我们不能够在终端中打印node2.js,因为模块化有主次,是node2变成了node1的一部分模块,但node2本身是不和node1产生联系的,除非我们导出(下面第三点做法)。
    • 全局可访问的意思是,该变量能够被导入进来的模块所识别。

Node 第十章 全局变量

全局变量的初始化
  • 全局变量应在使用之前被初始化。如果尝试访问一个未定义的全局变量,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

Node 第十章 全局变量

  • 简化代码:使用 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
表示当前模块的所在目录的绝对路径表示当前模块文件的绝对路径,包括文件名和文件扩展名

Node 第十章 全局变量

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}`);
});
// 当进程退出时,输出退出码