2017-08-01 19 views
5

Tôi đã trải qua một số hướng dẫn trực tuyến trên Node.js. Những gì tôi hiểu là, về việc sử dụng require(./file-path) chức năng, nút được nội dung của tập tin đó và kết thúc tốt đẹp bên trong một chức năng ngay lập tức gọiTại sao chúng ta cần phải vượt qua module.exports như một tham số vì chúng ta đã truyền mô-đun như một tham số?

(function(exports, require, module, __filename, __dirname) { 
    // content 
}()) 

tôi hiểu sự khác biệt giữa exportsmodule.exports. Đó là tất cả những gì tôi có thể thấy trên internet khi tìm kiếm câu hỏi trên. Nhưng câu hỏi của tôi là gì, tại sao chúng ta cần phải vượt qua module.exportsmodule cho gói IIFE? Chúng tôi có thể đã thông qua mô-đun một mình và sau đó nhận được module.exports từ nó. Có lợi thế nào khi làm như thế này không? Thông thường, khi chúng ta truyền một đối tượng đến một hàm, chúng ta không cần phải chuyển đổi thêm object.property.

Trả lời

3

Câu trả lời là: lý do lịch sử.

Bạn nói đúng, chúng tôi chỉ có thể có moduleexports sẽ không cần thiết nhưng vẫn còn ở đó để tương thích ngược.

Nó từng là thời điểm khi trình bao bọc mô-đun được thay đổi trong mọi bản phát hành bản vá.

Trong Node 0.1.11 module wrapper là:

var wrapper = "function (__filename) { "+ 
       " var onLoad; "+ 
       " var onExit; "+ 
       " var exports = this; "+ 
       content+ 
       "\n"+ 
       " this.__onLoad = onLoad;\n"+ 
       " this.__onExit = onExit;\n"+ 
       "};\n"; 

Xem: https://github.com/nodejs/node/blob/v0.1.11/src/node.js#L167#L177

Như bạn có thể thấy exports là giống như this rằng chức năng bao bọc được gọi với. Bạn không thể trao đổi nó với một đối tượng mới và thậm chí bạn không thể thêm một số khóa dành riêng cho nó - ví dụ: bạn không thể xuất một cách an toàn một tài sản có tên là __onExit.

Sau đó, trong 0.1.12 đó là:

var wrapper = "function (__filename, exports) { " + content + "\n};"; 

Xem: https://github.com/nodejs/node/blob/v0.1.12/src/node.js#L243-L245

Ở đây exports là một đối tượng cung cấp là một trong những tranh cãi nhưng bạn không thể trao đổi nó với một đối tượng mới, bạn chỉ có thể thêm hoặc loại bỏ các thuộc tính khỏi đối tượng mà bạn nhận được.

Sau đó, 0.1.13 là người đầu tiên có điều này, tức là requireinclude:

var wrapper = "function (__filename, exports, require, include) { " + content + "\n};"; 

Xem: https://github.com/nodejs/node/blob/v0.1.13/src/node.js#L225-L227

Sau đó 0.1.14 là người đầu tiên có __module (với dấu gạch dưới) trong các wrapper (và rằng giảm include):

var wrapper = "var __wrap__ = function (__module, __filename, exports, require) { " 
      + content 
      + "\n}; __wrap__;"; 

Xem: https://github.com/nodejs/node/blob/v0.1.14/src/node.js#L280-L284

Và 0,1.16 là người đầu tiên có một cuộc tranh luận module (không có dấu gạch dưới) trong wrapper:

var wrapper = "var __wrap__ = function (exports, require, module, __filename) { " 
      + content 
      + "\n}; __wrap__;"; 

Xem: https://github.com/nodejs/node/blob/v0.1.16/src/node.js#L444-L448

Nó được thay đổi nhiều lần sau đó nhưng đây là thời gian mà module đã giới thiệu làm các exports không cần thiết nữa nhưng vẫn còn là một phím tắt hữu ích, cho phép bạn sử dụng:

exports.a = 1; 
exports.b = 2; 
exports.c = 3; 

thay vì:

0.123.
module.exports.a = 1; 
module.exports.b = 2; 
module.exports.c = 3; 

mặc dù trong thực tế nếu không có exports sau đó người ta sẽ thường viết:

const exports = module.exports; 
exports.a = 1; 
exports.b = 2; 
exports.c = 3; 

hoặc nhiều khả năng:

module.exports = { 
    a: 1, 
    b: 2, 
    c: 3, 
}; 

hay, có một số kiểm tra trong các công cụ phân tích tĩnh:

const a = 1; 
const b = 2; 
const c = 3; 
module.exports = { a, b, c }; 

Có nhiều cách để làm điều đó, đó là một cơ chế linh hoạt.

+0

Đánh tôi với nó. Đã sớm hơn tôi nhớ. – OrangeDog

2

Ban đầu chỉ có exportsrequire. Sau đó, module được thêm vào theo cách tương thích ngược, để cho phép (trong số những thứ khác) ghi đè hoàn toàn đối tượng xuất.

+0

Hãy để tôi xem tôi có thể tìm thấy thay đổi không. Tôi nghĩ rằng đó là một nơi nào đó xung quanh v0.6. – OrangeDog

+0

Sau đó khi họ thêm mô-đun, tại sao họ không xóa module.exports sau đó? Họ có thể nhận được nó anyway từ đối tượng mô-đun. –

+0

@MELWINVINCENT vì điều đó sẽ làm hỏng cả hai mô-đun cũ bằng nền tảng mới và mô-đun mới sử dụng nền tảng cũ. – OrangeDog

Các vấn đề liên quan