path.resolve 与 path.join 的区别详解
相信大家一定用过 path.resolve()
或 path.join()
,特别是 Webpack、Rollup、Vite 等构建工具,再熟悉不过了。
path.resolve(__dirname, 'src/index.js')
像这个例子,用 path.join(__dirname, 'src/index.js')
所得到的结果也是完全一样的。
那么它俩究竟有何不同,在什么情况下使用才能体现出区别呢?
path.resolve
该函数接受「零或多个」字符串类型的路径参数,并返回一个 normalized 的「绝对路径」。
path.resolve(path1, path2, ..., pathN)
有以下几个特点:
- 其中 zero-length 的参数会被忽略,比如
''
(空字符串)和'.'
(表示当前目录)。 - 以
/
开头的参数会被当作文件系统根路径,不以../
或./
开头的参数会被当作是目录。 - 若参数不为字符串类型,则会抛出 TypeError。
- 若不传递任何参数时,返回 Node 进程的当前工作目录。因此
path.resolve() === process.cwd()
结果为true
。 - 结果返回之前其内部也会做类似
path.normalize()
的路径规范化处理。
看例子:
path.resolve('/a', 'b', 'c') // return: "/a/b/c" path.resolve('/a', '/b', 'c') // return: "/b/c" path.resolve('/a', '/b', '/c') // return: "/c"
其实在官网就描述得很清晰了。无非就是,「从右到左」一个一个参数开始解析,每解析一个就将其加到原来路径的「前面」,参数之间使用平台对应的路径分隔符连接。若能拼接成一个绝对路径,就停止解析并立即返回。如果将所有参数都解析完,仍然无法拼凑得出一个绝对路径,那么就讲这些参数的结果拼到当前工作目录中,以得出绝对路径。
因此,上述示例内部解析过程如下:
"c" -> "b/c" -> "/a/b/c" "c" -> "/b/c" "/c"
假设有 path.resolve('a', 'b')
,就是 "b" -> "a/b" -> "process.cwd()/a/b"
的过程,相当于 path.resolve(process.cwd(), 'a', 'b')
。其中 proccess.cwd()
就是当前工作目录。
**个人认为,更好的理解倒是「从左往右」看,将 path.resolve()
方法看作 Shell 的 cd
操作,只是前者不管文件系统是否存在此目录或文件。**如伪代码:
path.resolve('/a', '/b', 'c') // 相当于 $ cd /a; cd /b; cd c
或许 path.resolve()
称为 path.cd()
更让人豁然开朗吧。
path.join
该函数接受「零或多个」字符串类型的路径参数,返回一个所有参数拼接起来的(相对/绝对)路径。
path.join(path1, path2, ..., pathN)
有以下几个特点:
- 其中 zero-length 的参数会被忽略,比如
''
(空字符串)和'.'
(表示当前目录)。 - 以
../
开头的参数认为是上一级目录。 - 第一个参数若以
/
会被认为是根目录,其他以/
开头的参数作用与./
相同。 - 若参数不为字符串类型,则会抛出 TypeError。
- 若不传递任何参数时,返回
.
(当前目录)。 - 结果返回之前其内部也会做类似
path.normalize()
的路径规范化处理。
看例子:
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"
其实不用看那么多,换个角度去理解或许更清晰,两个步骤:
- 用相加运算符
+
将所有参数连接起来(参数之间用/
连接)。 - 使用
path.normalize()
对相加后的字符串路径作规范化处理。
有人可能会问,path.normalize()
又是干嘛的啊。很简单:把 ./
、../
翻译成对应路径;把多余无用的路径连接符干掉(如 a//b
=> a/b
);将路径连接符转换为特定平台的连接符(比如 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"
区别
以几个示例做总结:
无参数时
path.resolve() // 返回当前工作目录,相当于 `process.cwd()`,是绝对路径。 path.join() // 返回 `.`(当前目录),是相对路径。
请注意「当前工作目录」和「当前目录」的区别。
有多个参数,且中间参数以 /
开头
path.resolve('/a', '/b', 'c') // 返回 `/b/c`,绝对路径。 path.join('/a', '/b', 'c') // 返回 `/a/b/c`,绝对路径。
path.resolve('a', '/b', 'c') // 返回 `/b/c`,绝对路径。 path.join('a', '/b', 'c') // 返回 `a/b/c`,相对路径。
相信大家都懂了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论