Câu hỏi Mục đích của module.exports của Node.js là gì và bạn sử dụng nó như thế nào?


Mục đích của module.exports của Node.js là gì và bạn sử dụng nó như thế nào?

Tôi dường như không thể tìm thấy bất kỳ thông tin nào về điều này, nhưng nó dường như là một phần khá quan trọng của Node.js như tôi thường thấy trong mã nguồn.

Theo Tài liệu Node.js:

mô-đun 

Một tham chiếu đến hiện tại    module. Đặc biệt module.exports   giống như đối tượng xuất khẩu. Xem    src/node.js để biết thêm thông tin.

Nhưng điều này không thực sự hữu ích.

Chính xác thì sao module.exports và một ví dụ đơn giản là gì?


1238
2018-03-15 11:56


gốc




Các câu trả lời:


module.exports là đối tượng thực sự được trả lại là kết quả của require gọi điện.

Các exports biến ban đầu được đặt thành cùng một đối tượng đó (tức là nó là viết tắt "bí danh"), vì vậy trong mã mô-đun, bạn thường viết một cái gì đó như thế này:

var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

để xuất (hoặc "phơi bày") các hàm phạm vi nội bộ myFunc1 và myFunc2.

Và trong mã gọi bạn sẽ sử dụng:

var m = require('./mymodule');
m.myFunc1();

nơi dòng cuối cùng cho thấy kết quả của require là (thường) chỉ là một đối tượng đơn giản có thuộc tính có thể được truy cập.

NB: nếu bạn ghi đè exports thì nó sẽ không còn ám chỉ đến module.exports. Vì vậy, nếu bạn muốn gán một đối tượng mới (hoặc một tham chiếu hàm) vào exports thì bạn cũng nên gán đối tượng mới đó cho module.exports


Cần lưu ý rằng tên được thêm vào exports đối tượng không nhất thiết phải giống với tên phạm vi nội bộ của mô-đun cho giá trị bạn đang thêm, vì vậy bạn có thể có:

var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

theo dõi bởi:

var m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName

1454
2018-03-15 12:00



Câu trả lời hay - dường như với tôi rằng 'phơi bày' sẽ là lựa chọn tốt hơn về thuật ngữ hơn là 'xuất khẩu' - UpTheCreek
À, tôi dường như đã tìm thấy nó ... commonjs.org/specs/modules/1.0 - aikeru
@ApopheniaOverload - bạn có thể thực hiện "exports.func1, exports.func2, v.v" để có nhiều phương thức được tiếp xúc từ một tệp. - hellatan
Yêu cầu mô-đun phải là var m = require ('./ mymodule');, với dấu chấm và dấu gạch chéo. Bằng cách này, Node.js biết chúng tôi đang sử dụng một mô-đun cục bộ. - Gui Premonsa
Hãy chắc chắn sử dụng: cú pháp yêu cầu ('./ module_name') vì, có thể có một số mô-đun node.js khác với tên nào đó và thay vì chọn mô đun của riêng bạn, nó sẽ chọn mô-đun được cài đặt với node.js - Sazid


Điều này đã được trả lời nhưng tôi muốn thêm một số làm rõ ...

Bạn có thể sử dụng cả hai exports và module.exports để nhập mã vào ứng dụng của bạn như thế này:

var mycode = require('./path/to/mycode');

Trường hợp sử dụng cơ bản bạn sẽ thấy (ví dụ: trong mã ví dụ ExpressJS) là bạn đặt thuộc tính trên exports đối tượng trong tệp .js mà bạn sau đó nhập bằng require()

Vì vậy, trong một ví dụ đếm đơn giản, bạn có thể có:

(counter.js):

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

... sau đó trong ứng dụng của bạn (web.js hoặc bất kỳ tệp .js nào khác):

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

Nói một cách đơn giản, bạn có thể nghĩ các tệp được yêu cầu như các hàm trả về một đối tượng duy nhất và bạn có thể thêm các thuộc tính (chuỗi, số, mảng, hàm, bất kỳ thứ gì) vào đối tượng được trả về bằng cách đặt chúng trên exports.

Đôi khi bạn sẽ muốn đối tượng được trả về từ require() gọi là một hàm bạn có thể gọi, thay vì chỉ là một đối tượng có thuộc tính. Trong trường hợp đó, bạn cũng cần phải thiết lập module.exports, như thế này:

(sayhello.js):

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js):

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

Sự khác biệt giữa xuất khẩu và module.exports được giải thích rõ hơn trong câu trả lời này ở đây.


194
2017-10-16 05:03



làm thế nào tôi có thể gọi yêu cầu một số mô-đun từ thư mục khác mà không có một số thư mục gốc như tôi? - Igal
@ user301639 bạn có thể sử dụng đường dẫn tương đối để đi qua hệ thống phân cấp hệ thống tệp. require bắt đầu liên quan đến thư mục bạn thực thi node app.js Tôi khuyên bạn nên đăng câu hỏi mới với các ví dụ về cấu trúc thư mục + mã rõ ràng để có câu trả lời rõ ràng hơn. - Jed Watson
Tôi đã phải tinh chỉnh ví dụ module.exports của bạn để làm cho nó hoạt động. tập tin: var sayHello = require('./ex6_module.js'); console.log(sayHello()); và mô-đun: module.exports = exports = function() { return "Hello World!"; } - Jason Lydon
Tìm thấy ví dụ gia tăng thực sự tốt và tôi đã sử dụng điều này để làm mới tâm trí của tôi mỗi khi tôi bị quá tải với những gì tôi đang làm với xuất khẩu. - munkee


Lưu ý rằng cơ chế mô-đun NodeJS dựa trên CommonJS các mô-đun được hỗ trợ trong nhiều triển khai khác như RequireJS, nhưng cũng SproutCore, CouchDB, Wakanda, OrientDB, ArangoDB, RingoJS, TeaJS, SilkJS, curl.js, hoặc thậm chí Adobe Photoshop (thông qua PSLib). Bạn có thể tìm thấy danh sách đầy đủ các triển khai đã biết đây.

Trừ khi mô-đun của bạn sử dụng các tính năng hoặc mô-đun cụ thể của nút, tôi rất khuyến khích bạn sau đó sử dụng exports thay vì module.exports  mà không phải là một phần của tiêu chuẩn CommonJSvà sau đó hầu như không được hỗ trợ bởi các triển khai khác.

Một tính năng cụ thể khác của NodeJS là khi bạn gán một tham chiếu đến một đối tượng mới exports thay vì chỉ thêm các thuộc tính và phương thức vào nó như trong ví dụ cuối cùng được cung cấp bởi Jed Watson trong chuỗi này. Cá nhân tôi sẽ không khuyến khích thực hành này như thế này phá vỡ hỗ trợ tham chiếu vòng tròn của cơ chế mô-đun CommonJS. Sau đó nó không được hỗ trợ bởi tất cả các triển khai và ví dụ Jed sau đó sẽ được viết theo cách này (hoặc một ví dụ tương tự) để cung cấp một mô-đun phổ quát hơn:

(sayhello.js):

exports.run = function() {
    console.log("Hello World!");
}

(app.js):

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

Hoặc sử dụng các tính năng ES6

(sayhello.js):

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js):

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

PS: Có vẻ như Appcelerator cũng triển khai các mô-đun CommonJS, nhưng không hỗ trợ tham chiếu vòng tròn (xem: Các mô đun Appcelerator và CommonJS (tham khảo bộ nhớ đệm và tham số vòng tròn))


53
2018-01-20 12:35





Một số điều bạn phải cẩn thận nếu bạn chỉ định một tham chiếu đến một đối tượng mới exports và / hoặc modules.exports:

1. Tất cả các thuộc tính / phương pháp trước đây được đính kèm với bản gốc exports hoặc là module.exports tất nhiên là bị mất vì đối tượng đã xuất hiện sẽ tham chiếu một đối tượng mới khác

Điều này là hiển nhiên, nhưng nếu bạn thêm phương thức đã xuất ở đầu mô-đun hiện có, hãy đảm bảo đối tượng đã xuất bản gốc không tham chiếu một đối tượng khác ở cuối

exports.method1 = function () {}; // exposed to the original exported object
exports.method2 = function () {}; // exposed to the original exported object

module.exports.method3 = function () {}; // exposed with method1 & method2

var otherAPI = {
    // some properties and/or methods
}

exports = otherAPI; // replace the original API (works also with module.exports)

2. Trong trường hợp một trong exports hoặc là module.exports tham chiếu một giá trị mới, chúng không tham chiếu đến cùng một đối tượng nữa

exports = function AConstructor() {}; // override the original exported object
exports.method2 = function () {}; // exposed to the new exported object

// method added to the original exports object which not exposed any more
module.exports.method3 = function () {}; 

3. Hậu quả khó khăn. Nếu bạn thay đổi tham chiếu cho cả hai exports và module.exports, khó nói API nào được hiển thị (có vẻ như module.exports thắng)

// override the original exported object
module.exports = function AConstructor() {};

// try to override the original exported object
// but module.exports will be exposed instead
exports = function AnotherConstructor() {}; 

31
2018-01-25 09:02





thuộc tính module.exports hoặc đối tượng xuất khẩu cho phép một mô-đun để chọn những gì cần được chia sẻ với ứng dụng

enter image description here

Tôi có một video trên module_export có sẵn đây


23
2017-09-03 19:01



Tôi hiểu bạn. cảm ơn - Kumaresan Perumal


Khi chia mã chương trình của bạn trên nhiều tệp, module.exports được sử dụng để xuất bản các biến và chức năng cho người tiêu dùng của một mô-đun. Các require() cuộc gọi trong tập tin nguồn của bạn được thay thế bằng tương ứng module.exports được tải từ mô-đun.

Ghi nhớ khi viết mô-đun

  • Tải mô-đun được lưu vào bộ nhớ cache, chỉ cuộc gọi ban đầu mới đánh giá JavaScript.
  • Có thể sử dụng các biến và hàm cục bộ bên trong một mô-đun, không phải mọi thứ cần được xuất.
  • Các module.exports đối tượng cũng có sẵn dưới dạng exports viết tắt. Nhưng khi trả về một hàm duy nhất, hãy luôn sử dụng module.exports.

module exports diagram

Theo: "Mô-đun Phần 2 - Viết mô-đun".


17
2017-08-06 21:05





liên kết giới thiệu giống như sau:

exports = module.exports = function(){
    //....
}

các thuộc tính của exports hoặc là module.exports , chẳng hạn như chức năng hoặc biến số, sẽ được hiển thị bên ngoài

có một cái gì đó bạn phải chú ý nhiều hơn: không override xuất khẩu.

tại sao ?

bởi vì xuất khẩu chỉ là tham chiếu của module.exports, bạn có thể thêm các thuộc tính vào xuất khẩu, nhưng nếu bạn ghi đè xuất, liên kết tham chiếu sẽ bị hỏng.

ví dụ tốt :

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

ví dụ tồi :

exports = 'william';

exports = function(){
     //...
}

Nếu bạn chỉ muốn hiển thị chỉ một hàm hoặc biến, như sau:

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

mô-đun này chỉ tiếp xúc với một chức năng và thuộc tính của tên là riêng tư cho bên ngoài.


8
2018-04-18 00:53





Có một số mô-đun mặc định hoặc hiện có trong node.js khi bạn tải xuống và cài đặt node.js như http, sys v.v.

Vì chúng đã có trong node.js, khi chúng ta muốn sử dụng các mô-đun này, về cơ bản chúng ta sẽ làm mô-đun nhập, nhưng tại sao? vì chúng đã có mặt trong node.js. Nhập khẩu giống như đưa chúng từ node.js và đưa chúng vào chương trình của bạn. Và sau đó sử dụng chúng.

Trong khi Xuất khẩu chính xác là ngược lại, bạn đang tạo mô-đun bạn muốn, giả sử mô-đun addition.js và đặt mô-đun đó vào node.js, bạn làm điều đó bằng cách xuất nó.

Trước khi tôi viết bất cứ điều gì ở đây, hãy nhớ, module.exports.additionTwo giống như exports.additionTwo


4
2017-07-27 20:49



là nó xuất khẩu hoặc xuất khẩu? - Siva Sankar Rajendran
Cảm ơn đã giúp đỡ :) - JumpMan


Một mô-đun đóng gói mã liên quan thành một đơn vị mã. Khi tạo một mô-đun, điều này có thể được hiểu là di chuyển tất cả các hàm liên quan vào một tệp.

Giả sử có một tệp Hello.js bao gồm hai hàm

sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

Chúng ta chỉ viết một hàm khi tiện ích của mã là nhiều hơn một cuộc gọi.

Giả sử chúng ta muốn tăng tiện ích của hàm này cho một tệp khác có tên World.js, trong trường hợp này xuất tệp có hình ảnh có thể thu được bằng module.exports.

Bạn chỉ có thể xuất cả hàm bằng mã được đưa ra dưới đây

var anyVariable={
 sayHelloInEnglish = function() {
      return "Hello";
    };
  sayHelloInSpanish = function() {
      return "Hola";
    }; 
}
module.export=anyVariable;

Bây giờ bạn chỉ cần yêu cầu tên tệp vào trong trình tự World.js để sử dụng các hàm đó

var world= require("./hello.js");

1
2018-04-22 16:04



Cảm ơn Nếu nó đã giúp bạn vui lòng chấp nhận câu trả lời của tôi :) - Shantanu Madane
Một chút muộn để đảng pal :) - Ben Taliadoros
@BenTaliadoros tôi cũng nghĩ rằng anh ấy đến trễ và tôi cũng nghĩ rằng đối tượng anyVariable của anh ấy có nhiều lỗi. dòng ở trên sayHelloInSpanish phương pháp không nên kết thúc bằng dấu chấm phẩy (;) và sayHelloInSpanish = chức năng là sai. Tất cả mọi thứ đều sai với đối tượng này. tôi sẽ chỉnh sửa câu trả lời của anh ấy - divine
chỉnh sửa bị tắt. Điều gì khác đã làm alphadogg chỉnh sửa trong câu trả lời này ?? - divine
Chỉ cần định dạng. Trừ khi một số điều es6 điên rồ của tôi tôi đã không đi qua, và tôi chắc chắn nó không, sau đó nó không hợp lệ JS ở tất cả - Ben Taliadoros