關於Node.js的__dirname,__filename,process.cwd(),./文件路徑的一些坑


探索

計算機不會欺騙人,一切按照規則執行,說找不到這個文件,那肯定就是真的找不到,至於為什么找不到,那就是因為我們理解有偏差,我最初理解的'./'是當前執行js文件所在的文件夾的絕對路徑,然后Node.js的理解卻不是這樣的,我們慢慢往下看。

Node.js中的文件路徑大概有 __dirname, __filename, process.cwd(), ./ 或者 ../,前三個都是絕對路徑,為了便於比較,./ 和 ../ 我們通過 path.resolve('./')來轉換為絕對路徑。

簡單說一下這幾個路徑的意思,:

__dirname: 獲得當前執行文件所在目錄的完整目錄名
__filename: 獲得當前執行文件的帶有完整絕對路徑的文件名
process . cwd ( ):獲得當前執行node命令時候的文件夾目錄名
. /: 文件所在目錄

先看一看我電腦當前的目錄結構:

syntax /
-nodejs /
- 1 .findLargest .js
- 2 .path .js
- 3 .fs .js
-regs
-regx .js
-test .txt

在 path.js 里面我們寫這些代碼,看看輸出是什么:

const path  =  require ( 'path' )
console . log ( '__dirname:' , __dirname )
console . log ( '__filename:' , __filename )
console . log ( 'process.cwd():' , process . cwd ( ) )
console . log ( './:' , path . resolve ( './' ) )

在當前目錄下也就是nodejs目錄運行 node path.js,我們看看輸出結果:

__dirname:  /Users /jawil /Desktop /nodejs /demo /ES6 -lottery /syntax /nodejs
__filename:  /Users /jawil /Desktop /nodejs /demo /ES6 -lottery /syntax /nodejs / 2 .path .js
process . cwd ( ):  /Users /jawil /Desktop /nodejs /demo /ES6 -lottery /syntax /nodejs
. /:  /Users /jawil /Desktop /nodejs /demo /ES6 -lottery /syntax /nodejs


然后在 項目根目錄ES6-lottery 目錄下運行 node syntax/nodejs/2.path.js,我們再來看看輸出結果:

__dirname:  /Users /jawil /Desktop /nodejs /demo /ES6 -lottery /syntax /nodejs
__filename:  /Users /jawil /Desktop /nodejs /demo /ES6 -lottery /syntax /nodejs / 2 .path .js
process . cwd ( ):  /Users /jawil /Desktop /nodejs /demo /ES6 -lottery
. /:  /Users /jawil /Desktop /nodejs /demo /ES6 -lottery


答案顯而易見?我們可以通過上面的例子對比,暫時得出表面的結論:

__dirname : 總是返回被執行的 js 所在文件夾的絕對路徑
__filename : 總是返回被執行的 js 的絕對路徑
process . cwd ( ) : 總是返回運行 node 命令時所在的文件夾的絕對路徑
. / : 跟 process . cwd ( ) 一樣,返回 node 命令時所在的文件夾的絕對路徑

但是,我們再來看看這個例子,我們在上面的例子加幾句代碼,然后:

我們在1.findLargest.js先加這句代碼

exports .=  1 ;

再來在剛才報錯的3.fs.js里面加這兩句代碼看看:

const test  =  require ( './1.findLargest.js' ) ;
console . log (test )

運行node syntax/nodejs/3.fs.js,最后看看結果:


再次疑惑

為什么都是讀取./1.findLargest.js文件,一樣的路徑,為什么require能獲取到,而readFile讀取不到呢?

於是查了不少資料,看到了一些關於require引入模塊的機制,從中學到了不少,也明白了為什么是這樣。

我們先了解一下require() 的基本用法:

下面的內容來自require() 源碼解讀,由阮一峰翻譯自《Node使用手冊》。
我們從第(2)小條的a部分可以看出:

2)如果 X 以  "./" 或者  "/" 或者  "../" 開頭
  a . 根據 X 所在的父模塊,確定 X 的絕對路徑。
  b . 將 X 當成文件,依次查找下面文件,只要其中有一個存在,就返回該文件,不再繼續執行。

const test = require('./1.findLargest.js')按照上面規則翻譯一遍就是:

根據1.findLargest.js所在的父模塊,確定1.findLargest.js的絕對路徑為/Users/jawil/Desktop/nodejs/demo/ES6-lottery/syntax/nodejs,關於其中的尋找細節這里不做探討。

先把1.findLargest.js當成文件,依次查找當前目錄下的1.findLargest.js,找到了,就返回該文件,不再繼續執行。

那么關於 ./ 正確的結論是:
在 require() 中使用是跟 __dirname 的效果相同,不會因為啟動腳本的目錄不一樣而改變,在其他情況下跟 process.cwd() 效果相同,是相對於啟動腳本所在目錄的路徑。

總結:

__dirname: 獲得當前執行文件所在目錄的完整目錄名
__filename: 獲得當前執行文件的帶有完整絕對路徑的文件名
process . cwd ( ):獲得當前執行node命令時候的文件夾目錄名
. /: 不使用require時候, . /與process . cwd ( )一樣,使用require時候,與__dirname一樣

只有在 require() 時才使用相對路徑(./, ../)的寫法,其他地方一律使用絕對路徑,如下:

// 當前目錄下
path . dirname (__filename )  +  '/path.js' ;
// 相鄰目錄下
path . resolve (__dirname ,  '../regx/regx.js' ) ;

最后看看改過之后的結果,不會報錯找不到文件了,不管在哪里執行這個腳本文件,都不會出錯了,防止以后踩坑。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM