При программировании в Node.js и ссылках на файлы, которые находятся где-то по отношению к вашему текущему каталогу, есть ли причина использовать переменную __dirname
вместо обычного ./
? Я использовал/до сих пор в своем коде и только что обнаружил существование __dirname
и по сути хочу знать, будет ли разумным преобразовать мой./в это, и если да, то почему это было бы умным идея.
В чем разница между __dirname и./в node.js?
Ответ 1
Сущность
В Node.js, __dirname
всегда находится каталог, в котором находится текущий исполняемый script (см. это). Поэтому, если вы набрали __dirname
в /d1/d2/myscript.js
, значение будет /d1/d2
.
В отличие от этого, .
дает вам каталог, из которого вы запустили команду node
в окне терминала (т.е. в вашем рабочем каталоге).
Исключением является использование .
с 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
.
Однако, если вы запустите script из /dir1
cd /dir1
node dir2/pathtest.js
вы получаете
. = /dir1
__dirname = /dir1/dir2
В этом случае ваш рабочий каталог был /dir1
, чтобы разрешить .
, но __dirname
по-прежнему разрешается /dir1/dir2
.
Использование .
внутри require
...
Если внутри dir2/pathtest.js
у вас есть вызов require
для включения файла внутри dir1
, вы бы всегда делаете
require('../thefile')
потому что путь внутри require
всегда относится к файлу, в котором вы его вызываете. Это не имеет никакого отношения к вашему рабочему каталогу.
Ответ 2
./
относится к текущему рабочему каталогу, за исключением функции 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
Но когда я запускаю тот же script из /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
не существует.