При программировании в 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 не существует.