node.js 中的 __dirname 和 ./ 有啥区别?

Posted

技术标签:

【中文标题】node.js 中的 __dirname 和 ./ 有啥区别?【英文标题】:What is the difference between __dirname and ./ in node.js?node.js 中的 __dirname 和 ./ 有什么区别? 【发布时间】:2011-12-29 04:51:02 【问题描述】:

在 Node.js 中编程并引用与当前目录相关的文件时,是否有任何理由使用 __dirname 变量而不是常规的 ./?到目前为止,我一直在我的代码中使用 ./ 并且刚刚发现 __dirname 的存在,并且本质上想知道将我的 ./ 转换为它是否明智,如果是,为什么会这样一个聪明的主意。

【问题讨论】:

tl;dr:所以,基本上,区别在于'./'和'process.cwd()'指的是调用脚本的终端的当前目录,而'__dirname'指的是到存储脚本的目录。 除非require 内部使用.require 中的路径始终相对于包含对 require 的调用的文件。 【参考方案1】:

./ 指的是当前工作目录,require() 函数除外。当使用require() 时,它会将./ 转换为当前调用文件的目录。 __dirname 始终是当前文件的目录。

例如,具有以下文件结构

/home/user/dir/files/config.json


  "hello": "world"

/home/user/dir/files/somefile.txt

text file

/home/user/dir/dir.js

var fs = require('fs');

console.log(require('./files/config.json'));
console.log(fs.readFileSync('./files/somefile.txt', 'utf8'));

如果我 cd 进入 /home/user/dir 并运行 node dir.js 我会得到

 hello: 'world' 
text file

但是当我从 /home/user/ 运行相同的脚本时,我得到了

 hello: 'world' 

Error: ENOENT, no such file or directory './files/somefile.txt'
    at Object.openSync (fs.js:228:18)
    at Object.readFileSync (fs.js:119:15)
    at Object.<anonymous> (/home/user/dir/dir.js:4:16)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

使用./require 一起使用,但不适用于fs.readFileSync。这是因为对于fs.readFileSync./ 转换为 cwd(在本例中为 /home/user/)。而/home/user/files/somefile.txt 不存在。

【讨论】:

哦,我以为 __dirname 是当前的工作目录...感谢您的澄清! 有什么办法可以用fs引用app的工作目录吗?例如,我正在尝试从工作目录/movies 加载文件,但由于我的模块位于文件/custom_modules/ 中,__dirname 尝试从/custom_modules/movies 获取电影 您可以使用./process.cwd()。见nodejs.org/api/process.html#process_process_cwd 值得注意的是,在 require 语句中使用 __dirname 而不是 ./ 不是一个好主意,因为尽管它们在节点中的行为相同,但它可能会导致 browserify 构建包的问题否则很容易避免。【参考方案2】:

要点

在 Node.js 中,__dirname 始终是当前执行脚本所在的目录 (see this)。因此,如果您在/d1/d2/myscript.js 中键入__dirname,则值将是/d1/d2

相比之下,. 为您提供了在您使用 pathfs 等库时在终端窗口中运行 node 命令的目录(即您的工作目录)。从技术上讲,它最初是您的工作目录,但可以使用 process.chdir() 进行更改。

当您使用.require() 时例外。 require 中的路径始终相对于包含对 require 的调用的文件。

例如...

假设你的目录结构是

/dir1
  /dir2
    pathtest.js

pathtest.js 包含

var path = require("path");
console.log(". = %s", path.resolve("."));
console.log("__dirname = %s", path.resolve(__dirname));

你会的

cd /dir1/dir2
node pathtest.js

你得到

. = /dir1/dir2
__dirname = /dir1/dir2

您的工作目录是/dir1/dir2,这就是. 解析的内容。由于pathtest.js 位于/dir1/dir2,这也是__dirname 解析的内容。

但是,如果您从 /dir1 运行脚本

cd /dir1
node dir2/pathtest.js

你得到

. = /dir1
__dirname = /dir1/dir2

在这种情况下,您的工作目录是/dir1,所以. 解析为,但__dirname 仍解析为/dir1/dir2

require 内使用....

如果在dir2/pathtest.js 中你有一个require 调用来包含dir1 中的一个文件,你会总是这样做

require('../thefile')

因为require 中的路径总是相对于你调用它的文件。它与您的工作目录无关。

【讨论】:

IMO,这个解释比接受的答案更清楚一些(你知道,“当前目录”在那里有点模棱两可)。 我同意。我将更改接受的答案。请记住,这个答案是在原始答案被接受 2.5 年后添加的,而我现在才注意到它(又过了 2 年)。 :) 迟到总比没有好! 值得注意的是./不是总是节点启动的目录。它以这种方式开始,但可以通过process.chdir() 进行更改。因此,./ 始终是当前工作目录,通常是启动节点的目录,除非您的代码显式更改了工作目录。 我对 Using 有点困惑。在 require 部分,如果 require 中的路径总是相对于您正在调用的文件,那么路径不应该是 require('../thefile') 而不是 require('../dir1/thefile') 吗?我认为 .. 已经将路径的当前位置从 dir2 拉回到 dir1 一级。你还需要把 dir1 放在路径中还是我错过了什么? 如果您需要在某个脚本中使用../someDir,并且您要从不同的文件夹运行该命令,您会怎么做?

以上是关于node.js 中的 __dirname 和 ./ 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应像 Node.js 一样获取`__dirname`

Node.js 中 __dirname 和 ./ 的区别

node上的__dirname和./的区别

13Node.js 全局对象

node.js 学习02

使用 ES6 模块时 Node.js 中 __dirname 的替代方案