path.resolve 與 path.join 的區(qū)別詳解

配圖源自 Freepik

前言

相信大家一定用過 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è)步驟:

  1. 用相加運(yùn)算符 + 將所有參數(shù)連接起來(參數(shù)之間用 / 連接)。
  2. 使用 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.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末何吝,一起剝皮案震驚了整個(gè)濱河市溉委,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌爱榕,老刑警劉巖瓣喊,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異黔酥,居然都是意外死亡藻三,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門跪者,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棵帽,“玉大人,你說我怎么就攤上這事渣玲《焊牛” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵忘衍,是天一觀的道長(zhǎng)逾苫。 經(jīng)常有香客問我,道長(zhǎng)枚钓,這世上最難降的妖魔是什么铅搓? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮搀捷,結(jié)果婚禮上星掰,老公的妹妹穿的比我還像新娘。我一直安慰自己嫩舟,他們只是感情好氢烘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著家厌,像睡著了一般威始。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上像街,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天黎棠,我揣著相機(jī)與錄音,去河邊找鬼镰绎。 笑死脓斩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的畴栖。 我是一名探鬼主播随静,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼吗讶!你這毒婦竟也來了燎猛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤照皆,失蹤者是張志新(化名)和其女友劉穎重绷,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膜毁,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昭卓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瘟滨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片候醒。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖杂瘸,靈堂內(nèi)的尸體忽然破棺而出倒淫,到底是詐尸還是另有隱情,我是刑警寧澤败玉,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布敌土,位于F島的核電站,受9級(jí)特大地震影響绒怨,放射性物質(zhì)發(fā)生泄漏纯赎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一南蹂、第九天 我趴在偏房一處隱蔽的房頂上張望犬金。 院中可真熱鬧,春花似錦六剥、人聲如沸晚顷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)该默。三九已至,卻和暖如春策彤,著一層夾襖步出監(jiān)牢的瞬間栓袖,已是汗流浹背匣摘。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裹刮,地道東北人音榜。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捧弃,于是被迫代替她去往敵國(guó)和親赠叼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容