Node.js 中 __dirname 和 ./ 的区别

2025年4月26日 | 7 分钟阅读

在 Node.js 中,尽管 __dirname 和 ./ 都用于管理文件和目录路径,但它们的功能和解析方式会因情况而异。全局变量 __dirname 代表脚本正在执行的目录的绝对路径。无论 Node.js 进程从何处启动,它都是固定的,在脚本运行时保持不变。__dirname 非常适合解析与脚本位置相关的路径,以确保文件系统操作的准确性和可移植性。然而,./ 表示 Node.js 进程启动的目录,也就是进程的当前工作目录。

与 __dirname 不同,./ 的值是动态的,如果使用 process.chdir() 修改工作目录,它可能会发生变化。由于 __dirname 与脚本的目录相关,而 ./ 依赖于 Node.js 进程的运行时上下文,因此即使两者都可以用于相对路径解析,它们在工作目录发生变化时也会有不同的表现。在讨论它们的区别之前,我们必须了解 __dirname 和 ./ 的语法和示例。

什么是 __dirname?

全局变量 __dirname 对于 Node.js 中的文件和目录管理至关重要。它返回当前正在执行的 JavaScript 文件所在的目录的绝对路径。与 process.cwd()(返回 Node.js 进程启动时的当前工作目录)不同,__dirname 特定于文件本身,独立于脚本的执行位置。

此功能特别适用于创建相对于当前脚本的文件和目录的绝对路径。它提供了一种在运行时确定当前文件目录的方法。在处理文件路径时,例如在 require 模块、读取或写入文件以及创建指向资源的相对路径时,__dirname 的值尤其有用。

语法

它具有以下语法:

  • __dirname 返回当前模块(脚本)的目录名称。
  • 它不受脚本执行位置的影响,这在解析与脚本位置相关的时非常有用。

示例

让我们以一个示例来说明 Node.js 中的 __dirname。

输出

 
Error reading file:   

说明

这个 Node.js 脚本演示了如何使用 __dirname 来一致地解析与脚本位于同一目录中的 data.txt 文件的路径。首先,导入所需的 path 和 fs(文件系统)模块。然后,使用 Path.join() 将目录路径与 'data.txt' 连接起来,在获取当前目录的绝对路径后构建完整的​​文件路径,这是使用 __dirname 全局变量完成的。该脚本然后使用 fs.readFile() 异步读取文件内容。如果发生错误(例如,文件不存在或无法打开),则会向控制台记录错误。如果读取操作成功,则会将文件内容打印到控制台。正如这个例子所示,由于 __dirname,文件可以被正确访问,无论脚本是从哪个工作目录执行的,这有助于解析相对于脚本位置的文件路径。

什么是 ./?

./ 符号用于解析相对于 Node.js 进程启动位置的文件路径,它在 Node.js 中表示当前工作目录。它的工作方式类似于 process.cwd() 方法,该方法也返回 Node.js 进程启动时的工作目录路径。但是,process.chdir() API 会动态更改 ./ 的基本路径,这允许我们在脚本执行期间修改当前工作目录。

./ 与 require() 方法的交互是其独特行为之一。require('./module') 中的 ./ 用于解析脚本执行时相对于当前工作目录的路径,而不是脚本文件本身的目录。因此,导入依赖于当前工作目录结构的模块效果很好。

然而,__dirname 提供当前正在执行的文件所在目录的绝对路径。当脚本文件和 Node.js 进程从同一目录启动时,./ 和 __dirname 可能会产生相似的结果。但是,当进程从不同目录启动时,它们会产生差异。./ 会适应工作目录,而 __dirname 则保持与文件位置一致,确保了可靠的文件路径解析。

这种区别对于维护 Node.js 应用程序中健壮且可预测的文件操作至关重要。

语法

它具有以下语法:

参数

  • const: 表示一个常量变量,不能被更改。
  • myModule: 变量名 myModule 将用于存储导入的模块。
  • require(): 一个 Node.js 函数,用于加载并返回括号中指定的模块或文件。
  • './myModule': 相对文件路径 "./myModule" 表明模块 myModule 位于当前目录 (./)。

示例

让我们以一个示例来说明 Node.js 中的 ./。

输出

 
__dirname:     
process.cwd():  
./ :  
filename:  /index.js
Directory of the current file:     

说明

这个 Node.js 程序演示了如何使用 path 等内置模块来获取不同的目录和文件路径信息。在导入 path 模块后,打印出 __dirname 的值,它表示当前脚本所在目录的绝对路径。此外,该程序会生成 process.cwd(),它显示当前工作目录,这可能与脚本的位置不符。使用 p.resolve("./"),它进一步解析 ./(当前目录的相对路径),并根据 Node.js 进程的启动路径生成一个绝对路径。然后,程序记录脚本本身的绝对路径 __filename。它使用 p.dirname(__filename) 显示正在执行脚本的目录名称进行比较。最后,它检查 __dirname 和 process.cwd() 是否不同,从而揭示了这两个值如何根据执行上下文而变化,尤其是在使用 process.chdir() 时。

Node.js 中 __dirname 和 ./ 的主要区别

Difference between __dirname and ./ in Node.js

Node.js 中 __dirname 和 ./ 之间有几个区别。主要区别如下:

特性__dirname./
定义它提供当前正在执行的脚本所在目录的绝对路径。它解析相对于 Node.js 进程启动时的当前工作目录的路径。
引用它直接指向文件系统上脚本文件的位置。它指向运行时 Node.js 进程的工作目录。
与 process.chdir() 的行为它始终保持一致,并且不受脚本执行期间工作目录更改的影响。如果使用 process.chdir() 更新工作目录,则动态更改。
在 require() 中的用法它不直接与 require() 一起使用。请使用 path 模块构建路径:path.join(__dirname, 'file.js')。它通常与 require() 一起使用,以相对于当前工作目录加载模块:require('./module')。
文件路径一致性无论脚本在哪里执行,它都能确保文件和目录路径的一致性。路径解析取决于 Node.js 进程启动的目录,可能导致不一致。
跨目录执行当脚本从不同目录执行时,它都能可靠地工作,始终指向脚本的位置。当 Node.js 进程从与脚本位置不同的目录启动时,行为会有所不同。
与 ES 模块的兼容性它在 ES 模块中不可用。可以通过 import.meta.url 与 fileURLToPath() 和 dirname() 来模拟。它在 CommonJS (.js) 和 ES 模块 (.mjs) 中行为相似。
静态文件使用场景它非常适合解析静态文件路径,例如 fs.readFile(path.join(__dirname, 'data.txt'))。它对静态文件的用途有限,因为它们可能指向不同的目录,具体取决于进程的启动位置。
典型用例它用于文件系统操作,如读取、写入或 require 相对于脚本位置的资源。它用于导入模块或解析相对于当前工作目录的路径。
便携性的最佳实践对于需要绝对路径或需要在不同环境中保持目录结构一致的应用程序至关重要。它适用于小型项目或应用程序始终从工作文件所在的目录运行的情况。
使用示例javascript const configPath = path.join(__dirname, 'config.json'); console.log(configPath);javascript const module = require('./module'); console.log(module);

结论

总之,在 Node.js 中处理文件路径需要同时使用 __dirname 和 ./,尽管它们的功能因情况而异。对于需要可靠的跨目录引用的文件系统操作,__dirname 非常理想,因为它提供了当前脚本所在目录的确定性绝对路径。无论脚本从何处执行,该路径始终准确,因为它不受当前工作目录更改的影响。然而,使用 process.chdir(),./ 根据当前工作目录解析相对路径,而当前工作目录在运行时可能会发生变化。因此,./ 适用于必须相对于执行上下文解析路径的情况,特别是在导入模块时。