path.join vs path.resolve với __dirname


141

Có sự khác biệt khi sử dụng cả hai path.joinpath.resolvevới __dirnameviệc giải quyết đường dẫn tuyệt đối trong Node.js không?

Có nên ưu tiên một trong số chúng khi được sử dụng như vậy (độ phân giải đường dẫn tuyệt đối là 90% trường hợp sử dụng)?

I E

const absolutePath = path.join(__dirname, some, dir);

so với

const absolutePath = path.resolve(__dirname, some, dir);

Cả hai phương pháp bình thường hóa đường dẫn.

Đây không phải là một bản sao của câu hỏi này vì câu trả lời được chấp nhận là sai.


Câu hỏi này đang được thảo luận trên meta
Nino Filiu

Điều này có trả lời câu hỏi của bạn không? Sự khác biệt giữa path.resolve và path.join invocation?
dùng5532169 ngày

Câu trả lời:


151

Vâng, có một sự khác biệt giữa các chức năng nhưng cách bạn đang sử dụng chúng trong trường hợp này sẽ dẫn đến kết quả tương tự.

path.jointrả về một đường dẫn chuẩn hóa bằng cách hợp nhất hai đường dẫn lại với nhau. Nó có thể trả về một đường dẫn tuyệt đối, nhưng không nhất thiết phải luôn luôn như vậy.

Ví dụ:

path.join('app/libs/oauth', '/../ssl')

quyết tâm app/libs/ssl

path.resolve, mặt khác, sẽ giải quyết một con đường tuyệt đối.

Chẳng hạn, khi bạn chạy:

path.resolve('bar', '/foo');

Đường dẫn được trả về sẽ là /foovì đó là đường dẫn tuyệt đối đầu tiên có thể được xây dựng.

Tuy nhiên, nếu bạn chạy:

path.resolve('/bar/bae', '/foo', 'test');

Con đường được trả về sẽ là /foo/testmột lần nữa bởi vì đó là con đường tuyệt đối đầu tiên có thể được hình thành từ phải sang trái.

Nếu bạn không cung cấp một đường dẫn chỉ định thư mục gốc thì các đường dẫn được cung cấp cho resolvehàm sẽ được thêm vào thư mục làm việc hiện tại. Vì vậy, nếu thư mục làm việc của bạn là /home/mark/project/:

path.resolve('test', 'directory', '../back');

quyết tâm

/home/mark/project/test/back

Sử dụng __dirnamelà đường dẫn tuyệt đối đến thư mục chứa tệp nguồn. Khi bạn sử dụng path.resolvehoặc path.joinhọ sẽ trả lại kết quả tương tự nếu bạn đưa ra cùng một đường dẫn sau __dirname. Trong những trường hợp như vậy, nó thực sự chỉ là vấn đề ưu tiên.


25
Nit: __dirnamelà đường dẫn tuyệt đối đến thư mục chứa tệp nguồn đang được thực thi, không phải thư mục làm việc hiện tại . Cái trước sẽ luôn giống nhau (trừ khi bạn di chuyển tệp); cái sau là một tham số trên toàn quy trình , thay đổi dựa trên cách bạn khởi chạy nút và liệu bạn có thay đổi nó hay không .
josh3736

2
Vì vậy, không có sự khác biệt giữa __dirnamepath.resolve(__dirname)?
georaldc

1
@georaldc: Tôi đã tìm thấy một: nút <<< "path = quiries ('path'); console.log (__ dirname); console.log (path.resolve (__ dirname))"
Colin

8
Tôi ghét phải nói nó, nhưng câu trả lời này thực sự không có ý nghĩa gì với tôi và tôi sẽ đánh giá cao một số làm rõ. Bạn nhận xét rằng path.resolve('/bar/bae', '/foo', 'test');về cơ bản loại bỏ đối số đầu tiên bởi vì /foo/test"là con đường tuyệt đối đầu tiên có thể được hình thành từ phải sang trái", nhưng bạn không giải thích được tại sao , vì vậy tôi thực sự không hiểu logic trong công việc. Ý tôi là tôi không có bất kỳ quan điểm nào về cấu trúc thư mục giả định mà bạn đang sử dụng trong ví dụ của bạn, vì vậy tôi không thể hiểu tại sao /bar/bae/foo/testkhông hợp lệ.
tạm

3
@t tạm_user_name Câu trả lời là đúng về path.resolvehành vi của nó ở đây: path.resolvehoạt động từ đối số ngoài cùng bên phải, di chuyển các phường bên trái qua danh sách đối số và chuẩn bị từng giá trị cho đến một đường dẫn tuyệt đối (cụ thể là bắt đầu bằng thư mục gốc /hoặc [cụ thể trong Windows ] một ký tự ổ đĩa) được xây dựng, sau đó trả về đường dẫn đó. Nó bỏ qua /bar/baebởi vì vào thời điểm đó, nó đã có con đường tuyệt đối /foo/testvà do đó không thấy có lý do gì để đi xa hơn.
Jamie Ridding

23
const absolutePath = path.join(__dirname, some, dir);

so với

const absolutePath = path.resolve(__dirname, some, dir);

path.joinsẽ ghép nối __dirnamelà tên thư mục của tệp hiện tại được nối với các giá trị của somedirvới dấu phân cách cụ thể của nền tảng.

Trong khi

path.resolvesẽ xử lý __dirname, somedirtức là từ phải sang trái chuẩn bị trước bằng cách xử lý nó.

nếu bất kỳ giá trị nào của somehoặc dirtương ứng với một đường dẫn gốc thì đường dẫn trước đó sẽ bị bỏ qua và xử lý phần còn lại bằng cách xem nó là gốc

Để hiểu rõ hơn về khái niệm này, hãy để tôi giải thích chi tiết hơn một chút như sau: -

Các path.joinpath.resolvehai phương pháp hoặc các chức năng của các module con đường cung cấp bởi nodejs khác nhau.

Trường hợp cả hai chấp nhận một danh sách các đường dẫn nhưng sự khác biệt đến trong kết quả tức là cách họ xử lý các đường dẫn này.

path.joinnối tất cả các phân đoạn đường dẫn cụ thể lại với nhau bằng cách sử dụng dấu tách riêng của nền tảng làm dấu phân cách, sau đó chuẩn hóa đường dẫn kết quả. Trong khi path.resolve()xử lý chuỗi các đường dẫn từ phải sang trái, với mỗi đường dẫn tiếp theo được chuẩn bị trước cho đến khi một đường dẫn tuyệt đối được xây dựng.

Khi không có đối số được cung cấp

Ví dụ sau đây sẽ giúp bạn hiểu rõ cả hai khái niệm: -

Tên tệp của tôi là index.jsvà thư mục làm việc hiện tại làE:\MyFolder\Pjtz\node

const path = require('path');

console.log("path.join() : ", path.join());
// outputs .
console.log("path.resolve() : ", path.resolve());
// outputs current directory or equalent to __dirname

Kết quả

λ node index.js
path.join() :  .
path.resolve() :  E:\MyFolder\Pjtz\node

path.resolve()phương thức sẽ xuất ra đường dẫn tuyệt đối trong đó là path.join()trả về. đại diện cho thư mục làm việc hiện tại nếu không có gì được cung cấp

Khi một số đường dẫn gốc được truyền dưới dạng đối số

const path=require('path');

console.log("path.join() : " ,path.join('abc','/bcd'));
console.log("path.resolve() : ",path.resolve('abc','/bcd'));

Kết quả tôi

λ node index.js
path.join() :  abc\bcd
path.resolve() :  E:\bcd

path.join()chỉ nối danh sách đầu vào với dấu phân tách cụ thể nền tảng trong khi path.resolve()xử lý chuỗi các đường dẫn từ phải sang trái, với mỗi đường dẫn tiếp theo được chuẩn bị trước cho đến khi một đường dẫn tuyệt đối được xây dựng.


Câu hỏi cụ thể là về path.join vs path.resolve với __dirname .
Bình Estus

Tôi đã cập nhật câu trả lời dựa trên ý kiến ​​của bạn, cảm ơn về bản cập nhật
samuelj90

3

từ doc cho path.resolve:

Đường dẫn kết quả được chuẩn hóa và dấu gạch chéo được loại bỏ trừ khi đường dẫn được giải quyết đến thư mục gốc.

Nhưng path.joindấu gạch chéo

Vì thế

__dirname = '/';
path.join(__dirname, 'foo/'); // '/foo/'
path.resolve(__dirname, 'foo/'); // '/foo'

từ 'bình thường hóa' có nghĩa là gì trong bối cảnh này?
apollo

1
@apollo path.n normalize (path)
lonr 19/12/18
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.