417

Khi lập trình trong Node.js và các tệp tham chiếu được đặt ở đâu đó liên quan đến thư mục hiện tại của bạn, có lý do nào để sử dụng __dirnamebiến thay vì chỉ là thông thường ./không? Tôi đã sử dụng ./ cho đến nay trong mã của tôi và chỉ phát hiện ra sự tồn tại của nó __dirname, và về cơ bản muốn biết liệu có thông minh để chuyển đổi ./ của tôi sang đó hay không, và nếu vậy, tại sao đó lại là một ý tưởng thông minh .

|
  • 40

    tl; dr: Về cơ bản, sự khác biệt là './' và 'process.cwd ()' đề cập đến thư mục hiện tại của thiết bị đầu cuối gọi tập lệnh, trong khi '__dirname' đề cập đến thư mục trong đó tập lệnh lưu trữ.

    – Ngô Nhật Khương 00:02:16 18/10/2014
699

Ý chính

Trong Node.js, __dirnameluôn là thư mục chứa tập lệnh hiện đang thực thi ( xem phần này ). Vì vậy, nếu bạn gõ __dirnamevào /d1/d2/myscript.js, giá trị sẽ là /d1/d2.

Ngược lại, .cung cấp cho bạn thư mục mà bạn đã chạy nodelệnh trong cửa sổ đầu cuối (tức là thư mục làm việc của bạn) khi bạn sử dụng các thư viện như pathfs. Về mặt kỹ thuật, nó bắt đầu như thư mục làm việc của bạn nhưng có thể được thay đổi bằng cách sử dụng process.chdir().

Ngoại lệ là khi bạn sử dụng .với require(). Đường dẫn bên trong requireluôn liên quan đến tệp chứa lệnh gọi đến require.

Ví dụ...

Giả sử cấu trúc thư mục của bạn là

/dir1
  /dir2
    pathtest.js

pathtest.jschứa

var path = require("path");
console.log(". = %s", path.resolve("."));
console.log("__dirname = %s", path.resolve(__dirname));

và bạn làm

cd /dir1/dir2
node pathtest.js

bạn lấy

. = /dir1/dir2
__dirname = /dir1/dir2

Thư mục làm việc của bạn là /dir1/dir2như vậy đó là những gì .giải quyết. pathtest.jsnằm ở /dir1/dir2đó là những gì __dirnamegiải quyết là tốt.

Tuy nhiên, nếu bạn chạy tập lệnh từ /dir1

cd /dir1
node dir2/pathtest.js

bạn lấy

. = /dir1
__dirname = /dir1/dir2

Trong trường hợp đó, thư mục làm việc của bạn là /dir1như vậy đó là những gì đã .giải quyết, nhưng __dirnamevẫn giải quyết /dir1/dir2.

Sử dụng .bên trong require...

Nếu bên trong dir2/pathtest.jsbạn có một requirecuộc gọi bao gồm một tập tin bên trong dir1bạn sẽ luôn luôn làm

require('../thefile')

bởi vì đường dẫn bên trong requireluôn liên quan đến tệp mà bạn đang gọi nó. Nó không có gì để làm với thư mục làm việc của bạn.

|
  • 1

    IMO, lời giải thích này rõ ràng hơn một chút so với câu trả lời được chấp nhận (bạn biết, "thư mục hiện tại" hơi mơ hồ ở đó).

    – Tạ Hoàng Điệp 17:30:36 09/12/2013
  • 1

    Tôi đồng ý. Tôi sẽ thay đổi câu trả lời được chấp nhận. Xin lưu ý rằng câu trả lời này đã được thêm 2,5 năm sau khi câu trả lời ban đầu được chấp nhận và tôi chỉ nhận thấy nó ngay bây giờ (2 năm sau). :) Muộn còn hơn không!

    – Hoàng Nguyên Giang 17:19:58 30/04/2015
  • 1

    Điều đáng chú ý ./là không phải lúc nào thư mục mà nút được khởi chạy. Nó bắt đầu theo cách đó, nhưng có thể được thay đổi thông qua process.chdir(). Vì vậy, ./luôn luôn là thư mục làm việc hiện tại, thường là nút thư mục được khởi chạy từ đó, trừ khi mã của bạn thay đổi rõ ràng thư mục làm việc.

    – Quang Duoc Dinh 20:32:13 04/06/2015
  • 1

    Tôi hơi bối rối về việc sử dụng. bên trong yêu cầu một phần, nếu đường dẫn bên trong yêu cầu luôn liên quan đến tệp bạn đang gọi, không phải đường dẫn nên được yêu cầu ('../ thefile') thay vì yêu cầu ('../ dir1 / thefile')? tôi nghĩ rằng .. đưa vị trí hiện tại của đường dẫn trở lại một cấp từ dir2 đến dir1 rồi. Bạn vẫn cần đặt dir1 vào đường dẫn hay tôi bỏ lỡ hiểu điều gì?

    – Đặng Thế Bình 03:13:00 07/04/2017
  • 1

    @andromada bắt tốt, đã sửa

    – Tạ Thi Thi 03:25:28 07/04/2017
149

./đề cập đến thư mục làm việc hiện tại, ngoại trừ trong require()chức năng. Khi sử dụng require(), nó dịch ./sang thư mục của tệp hiện tại được gọi. __dirnameluôn là thư mục của tập tin hiện tại

Ví dụ: với cấu trúc tệp sau

/home/user/dir/files/config.json

{
  "hello": "world"
}

/home/user/dir/files/somefile.txt

text file

/home/user/dir/dir.js

var fs = require('fs');

console.log(require('./files/config.json'));
console.log(fs.readFileSync('./files/somefile.txt', 'utf8'));

Nếu tôi cdvào /home/user/dirvà chạy node dir.jstôi sẽ nhận được

{ hello: 'world' }
text file

Nhưng khi tôi chạy cùng một kịch bản từ /home/user/tôi nhận được

{ hello: 'world' }

Error: ENOENT, no such file or directory './files/somefile.txt'
    at Object.openSync (fs.js:228:18)
    at Object.readFileSync (fs.js:119:15)
    at Object.<anonymous> (/home/user/dir/dir.js:4:16)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

Sử dụng ./làm việc với requirenhưng không cho fs.readFileSync. Đó là bởi vì fs.readFileSync, ./dịch sang cwd (trong trường hợp này /home/user/). /home/user/files/somefile.txtkhông tồn tại.

|

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.