前言
相信大家一定用過 path.resolve()
或 path.join()
,特別是 Webpack秸滴、Rollup、Vite 等構(gòu)建工具募判,再熟悉不過了荡含。
path.resolve(__dirname, 'src/index.js')
像這個(gè)例子,用 path.join(__dirname, 'src/index.js')
所得到的結(jié)果也是完全一樣的届垫。
那么它倆究竟有何不同释液,在什么情況下使用才能體現(xiàn)出區(qū)別呢?
path.resolve
該函數(shù)接受「零或多個(gè)」字符串類型的路徑參數(shù)装处,并返回一個(gè) normalized 的「絕對(duì)路徑」误债。
path.resolve(path1, path2, ..., pathN)
有以下幾個(gè)特點(diǎn):
- 其中 zero-length 的參數(shù)會(huì)被忽略,比如
''
(空字符串)和'.'
(表示當(dāng)前目錄)妄迁。- 以
/
開頭的參數(shù)會(huì)被當(dāng)作文件系統(tǒng)根路徑寝蹈,不以../
或./
開頭的參數(shù)會(huì)被當(dāng)作是目錄。- 若參數(shù)不為字符串類型登淘,則會(huì)拋出 TypeError箫老。
- 若不傳遞任何參數(shù)時(shí),返回 Node 進(jìn)程的當(dāng)前工作目錄黔州。因此
path.resolve() === process.cwd()
結(jié)果為true
耍鬓。- 結(jié)果返回之前其內(nèi)部也會(huì)做類似
path.normalize()
的路徑規(guī)范化處理。
看例子:
path.resolve('/a', 'b', 'c') // return: "/a/b/c"
path.resolve('/a', '/b', 'c') // return: "/b/c"
path.resolve('/a', '/b', '/c') // return: "/c"
其實(shí)在官網(wǎng)就描述得很清晰了流妻。無非就是牲蜀,「從右到左」一個(gè)一個(gè)參數(shù)開始解析,每解析一個(gè)就將其加到原來路徑的「前面」绅这,參數(shù)之間使用平臺(tái)對(duì)應(yīng)的路徑分隔符連接各薇。若能拼接成一個(gè)絕對(duì)路徑,就停止解析并立即返回君躺。如果將所有參數(shù)都解析完,仍然無法拼湊得出一個(gè)絕對(duì)路徑开缎,那么就講這些參數(shù)的結(jié)果拼到當(dāng)前工作目錄中棕叫,以得出絕對(duì)路徑。
因此奕删,上述示例內(nèi)部解析過程如下:
"c" -> "b/c" -> "/a/b/c"
"c" -> "/b/c"
"/c"
假設(shè)有 path.resolve('a', 'b')
俺泣,就是 "b" -> "a/b" -> "process.cwd()/a/b"
的過程,相當(dāng)于 path.resolve(process.cwd(), 'a', 'b')
。其中 proccess.cwd()
就是當(dāng)前工作目錄伏钠。
個(gè)人認(rèn)為横漏,更好的理解倒是「從左往右」看,將 path.resolve()
方法看作 Shell 的 cd
操作熟掂,只是前者不管文件系統(tǒng)是否存在此目錄或文件缎浇。如偽代碼:
path.resolve('/a', '/b', 'c')
// 相當(dāng)于
$ cd /a; cd /b; cd c
或許
path.resolve()
稱為path.cd()
更讓人豁然開朗吧。
path.join
該函數(shù)接受「零或多個(gè)」字符串類型的路徑參數(shù)赴肚,返回一個(gè)所有參數(shù)拼接起來的(相對(duì)/絕對(duì))路徑素跺。
path.join(path1, path2, ..., pathN)
有以下幾個(gè)特點(diǎn):
- 其中 zero-length 的參數(shù)會(huì)被忽略,比如
''
(空字符串)和'.'
(表示當(dāng)前目錄)誉券。- 以
../
開頭的參數(shù)認(rèn)為是上一級(jí)目錄指厌。- 第一個(gè)參數(shù)若以
/
會(huì)被認(rèn)為是根目錄,其他以/
開頭的參數(shù)作用與./
相同踊跟。- 若參數(shù)不為字符串類型踩验,則會(huì)拋出 TypeError。
- 若不傳遞任何參數(shù)時(shí)商玫,返回
.
(當(dāng)前目錄)箕憾。- 結(jié)果返回之前其內(nèi)部也會(huì)做類似
path.normalize()
的路徑規(guī)范化處理。
看例子:
path.join('a', 'b', 'c') // return: "a/b/c"
path.join('/a', 'b', 'c') // return: "/a/b/c"
path.join('/a', '/b', 'c') // return: "/a/b/c"
path.join('/a', '/b', '/c') // return: "/a/b/c"
其實(shí)不用看那么多决帖,換個(gè)角度去理解或許更清晰厕九,兩個(gè)步驟:
- 用相加運(yùn)算符
+
將所有參數(shù)連接起來(參數(shù)之間用/
連接)。- 使用
path.normalize()
對(duì)相加后的字符串路徑作規(guī)范化處理地回。
有人可能會(huì)問扁远,path.normalize()
又是干嘛的啊。很簡(jiǎn)單:把 ./
刻像、../
翻譯成對(duì)應(yīng)路徑畅买;把多余無用的路徑連接符干掉(如 a//b
=> a/b
);將路徑連接符轉(zhuǎn)換為特定平臺(tái)的連接符(比如 Unix 的 /
细睡,Windows 的 \
)谷羞。
因此,可以把 path.join('/a', '/b', 'c')
理解成這樣:
let args = ['/a', '/b', 'c']
let str = args.join('/') // "/a//b/c"
str = path.normalize(str) // "/a/b/c"
區(qū)別
以幾個(gè)示例做總結(jié):
無參數(shù)時(shí)
path.resolve() // 返回當(dāng)前工作目錄溜徙,相當(dāng)于 `process.cwd()`湃缎,是絕對(duì)路徑。
path.join() // 返回 `.`(當(dāng)前目錄)蠢壹,是相對(duì)路徑嗓违。
?? 請(qǐng)注意「當(dāng)前工作目錄」和「當(dāng)前目錄」的區(qū)別。
有多個(gè)參數(shù)图贸,且中間參數(shù)以 /
開頭
path.resolve('/a', '/b', 'c') // 返回 `/b/c`蹂季,絕對(duì)路徑冕广。
path.join('/a', '/b', 'c') // 返回 `/a/b/c`,絕對(duì)路徑偿洁。
path.resolve('a', '/b', 'c') // 返回 `/b/c`撒汉,絕對(duì)路徑。
path.join('a', '/b', 'c') // 返回 `a/b/c`涕滋,相對(duì)路徑睬辐。
相信大家都懂了。
The end.